diff options
Diffstat (limited to 'website/static/security')
133 files changed, 18911 insertions, 65 deletions
diff --git a/website/static/security/advisories/FreeBSD-EN-26:01.devinfo.asc b/website/static/security/advisories/FreeBSD-EN-26:01.devinfo.asc new file mode 100644 index 0000000000..fffa00bdf3 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:01.devinfo.asc @@ -0,0 +1,127 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:01.devinfo Errata Notice + The FreeBSD Project + +Topic: devinfo output formatting regression + +Category: core +Module: devinfo +Announced: 2026-01-27 +Affects: FreeBSD 15.0 +Corrected: 2025-12-19 18:16:12 UTC (stable/15, 15.0-STABLE) + 2026-01-27 19:15:45 UTC (releng/15.0, 15.0-RELEASE-p2) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +devinfo(8) is a tool to report information about devices present in a system +including resources used by devices such as MMIO regions and interrupts. + +libxo is a library that provides both "human-readable" and structured text +output (e.g. JSON and XML). + +II. Problem Description + +Changes made during the development cycle of 15.0 to adapt devinfo(8) to use +libxo unintentionally altered the human-readable output breaking existing tools +that parsed the output. + +III. Impact + +This bug broke the Intel nvmupdate tool available in the +sysutils/intel-nvmupdate port. There may be other utilities that are also +broken. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms +can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +2) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:01/devinfo.patch +# fetch https://security.FreeBSD.org/patches/EN-26:01/devinfo.patch.asc +# gpg --verify devinfo.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ ed6612dea24f stable/15-n281586 +releng/15.0/ 6a192c14d244 releng/15.0-n281000 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=291510> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:01.devinfo.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NCkACgkQbljekB8A +Gu+8tA//fEWpN3LE3MMstQzJM9EaQqO0Yt2PBGWhg+pR99i/Bx1Xcsmm+8zMhbx9 +2HB99/x91xVmkhaLISgLsK+tAB2vPCln1dpAt8K/nQxo/+AgF5oNdRI5sytzjhsZ +MxfAECJ81MtT83isA2sJpRbp6pYA3yPj9ab2C7V2I9GQLRK6/Fy8MhvuwHlc3Y0S +LgMSn8wOH4vRZ+dXn8JgPA38hbSnEpoWPMWaREQJYwTO5zKJw/TW4/tWaeyZOZd7 +fMxv22xuB6Bta3mTL9sWwYnGN4Ig0miBQstBto6UQnXkm7qZ1Av7MLM2UvZG44Ol +cGDtLyngyxhlEdVGu0AcO3AP2F4s1ot2g9DjC39/dIfRqlSrqjg0elm9N4pXeT0Z +5u9pBkea8z9aAkkxMyCBqROLpnWzdSKAW7MEAmRuZBrdczkfAGulvWJBEsPEu9ZW +wldCugRHxVO+5r9Mq11InRVcM1Jfkv7ZqH/5p1GHdDbUUlqdMC/H1P0oXDfowx9h +m/LJTP1FQyCDJr2rtR4JHRo7ifQJwpMVaKWDfbBKtIHlsq27woEy8dZIad9WyAAN +pvC4wq7PPg4WZ1HB54CUmAD5y49HuHeaS3KLA8ir4BwmdFmSC0KWQGpHQDgmh+Gt +xU7Sl+e4gJpu+zlD6I5pn7JTaz0DqIFdyzckBxEUBlmPkIETM+s= +=mQty +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:02.arm64.asc b/website/static/security/advisories/FreeBSD-EN-26:02.arm64.asc new file mode 100644 index 0000000000..ceb386017f --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:02.arm64.asc @@ -0,0 +1,137 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:02.arm64 Errata Notice + The FreeBSD Project + +Topic: arm64 SVE signal context misalignment + +Category: core +Module: arm64 +Announced: 2026-01-27 +Affects: FreeBSD 15.0 and 14.3 +Corrected: 2026-01-13 16:27:47 UTC (stable/15, 15.0-STABLE) + 2026-01-27 19:15:46 UTC (releng/15.0, 15.0-RELEASE-p2) + 2026-01-26 14:47:24 UTC (stable/14, 14.3-STABLE) + 2026-01-27 19:16:11 UTC (releng/14.3, 14.3-RELEASE-p8) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +Scalable Vector Extension (SVE) is an extension of the arm64 instruction set +providing SIMD functionality. + +II. Problem Description + +When a signal is delivered to a thread, the kernel saves the thread's usermode +register values and stores them on the interrupted thread's stack prior to +invoking the signal handler. + +When SVE is present, SVE registers must be saved as well. This register context +was not properly aligned when written out to userspace, and a subsequent request +to restore that context could fail as a result. + +III. Impact + +Processes could crash unexpectedly after handling a signal. + +IV. Workaround + +No workaround is available. Non-arm64 systems are not affected, and arm64 +systems without SVE are not affected. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms +can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r now + +2) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/EN-26:02/arm64-15.patch +# fetch https://security.FreeBSD.org/patches/EN-26:02/arm64-15.patch.asc +# gpg --verify arm64-15.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/EN-26:02/arm64-14.patch +# fetch https://security.FreeBSD.org/patches/EN-26:02/arm64-14.patch.asc +# gpg --verify arm64-14.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 683decf362ce stable/15-n281851 +releng/15.0/ 679b1a810e0e releng/15.0-n281001 +stable/14/ bcd6bb8067d1 stable/14-n273416 +releng/14.3/ 3ba856f715ca releng/14.3-n271456 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:02.arm64.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NCwACgkQbljekB8A +Gu/mSxAAwNJzUNx/bCFoGEoV1vkM5aUOd4lBnFyH/aeRUP/R8bKWQ4ydxiZTfd8m +m+ltioN//WUsP88h6OaAw4JeZBt4HCNi3Pj0fGyu0z4zCjFuKL/1k78Vl51Zt3pJ +bWJBr6WJ5JVmTzf3edbTpa6KA8uKH9JYdpwBsW6ACklBExFyjlYBBblxjWxNP4zo +WPzaYBqGQ/ZQqcQMF06n1M//ufvkHI++R3sOhGzuXz/PJlaUWhn5hblfw0iFt1Py +G3il68l+ONnPiXIkKRzEUCFoYO8feYsj4xK52hAik904JVqJLqUpkPeWgT7bRhzi +YUruypFE5Nt6RCPQ74dKZrshfdGcKeA1pVMAt8QC2e3DzWPYWjVCJiDlYD/kIvls +d/YiGieYs4cbVlX3FS1xWAs3MgN4osyfj/a5fTeSjuTcqjACW0g6xQRLW4LwMZ4V +rH6vm/gRf5/gheFOKokZh/ES3CKQFEXunGdn1ObWd1VKZU77LvVQLsI4J2pXhVYf +CqdU1qs80Qk13K7QmGMt6oRVp0IkM7NRIRivznOLUD0/SAtEdTb3G7gwJAR+AE0U +y61Bsmo4ujOTAGHH5gNAPX9xSWUlItYNTm5shKy6Xv5bQCY04Zi3S2ztXi0NkmX3 +4xWdz9v7/d1CPLCndgWHHDgnZuG3rUH6ueJCDQhtITcnD81w/5U= +=utLQ +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:03.vm.asc b/website/static/security/advisories/FreeBSD-EN-26:03.vm.asc new file mode 100644 index 0000000000..dd79584d27 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:03.vm.asc @@ -0,0 +1,144 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:03.vm Errata Notice + The FreeBSD Project + +Topic: The page fault handler fails to zero memory + +Category: core +Module: vm +Announced: 2026-01-27 +Affects: All supported versions of FreeBSD. +Corrected: 2025-12-15 10:37:54 UTC (stable/15, 15.0-STABLE) + 2026-01-27 19:15:47 UTC (releng/15.0, 15.0-RELEASE-p2) + 2025-12-15 10:42:28 UTC (stable/14, 14.3-STABLE) + 2026-01-27 19:16:12 UTC (releng/14.3, 14.3-RELEASE-p8) + 2026-01-26 15:18:32 UTC (stable/13, 13.4-STABLE) + 2026-01-27 19:16:34 UTC (releng/13.5, 13.5-RELEASE-p9) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The mmap(2) system call allows applications and system libraries to allocate +heap memory using the MAP_ANON flag. The system call allocates virtual memory +in the calling thread's address space and physical memory is allocated on +demand as page faults occur. Memory allocated this way is guaranteed to be +zero-filled. + +II. Problem Description + +Under some conditions, the physical pages allocated and mapped by the kernel +may not be zero-filled. + +III. Impact + +This bug has been observed to cause process crashes. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) +utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r now + +2) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-15.patch +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-15.patch.asc +# gpg --verify vm-15.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-14.patch +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-14.patch.asc +# gpg --verify vm-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-13.patch +# fetch https://security.FreeBSD.org/patches/EN-26:03/vm-13.patch.asc +# gpg --verify vm-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 3c0942f99209 stable/15-n281508 +releng/15.0/ 6e279feb40be releng/15.0-n281002 +stable/14/ 99f641267d44 stable/14-n272998 +releng/14.3/ de311ee39b3f releng/14.3-n271457 +stable/13/ babac9d7bc05 stable/13-n259725 +releng/13.5/ 4967e14ba25b releng/13.5-n259188 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:03.vm.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NC8ACgkQbljekB8A +Gu/4KhAAgF/05mLRDs9wlSC1BrN5xZf6zoFdrsj0BC72miZD1qQXe9VtxzJINMLu +b/jbKYT1ILPEXGhHX7epjc4GEM1Eq/kUJnTb35jnkFN63stMn1MX1nqtSNxLzj5f +tJcsb2Atp/3EkNMhcFwFmolQ2qSdQG+s7xDZhHI/hNi5CS/8B7W59LZI3tWXJujM +AbTiHZZSS68RA/co0lmbDYtLMkFEuQBLdcDAdfOHL5+rV2/QIAVYBdqiynVx+cia +iJBbwBuOjiMWSdqP9JiSRnd1HhW3dMUMJTlZFmyGiQNmS+lYE1AgLgPdMPwSReO8 ++79yUfIrFUqWpG6lM33a9T/t3jN8ejZsYRO8OFghvtaePJvUm/P6D0n0werR8PaE +lI9u7BlBqpX9PJ4FUJmUCHAojqXH6msT2RXLg5GcLhjlApMUi2hAcNuT9tp7/+4A +ekc0/sZqJdrcWTmu00w6Tpk9zohW/MX/DHxNEj4SPn5dpjvz9QttaCpNJNyNARuU +GdzZc8poPk3mpTcawABAD0LItpW6d2XLUehtgaWRc5mDoKZj5GIfLjDmqIqqxe9k +C9e6bhL+1QSZQ2HTTNl8e/xoUX+D2pAiE4GkpRSc6u6ZZ3BOQ+fRwbZlnFSz6diT +IIkUddz63TCmxPiiZiJs7XZFZMpx2wJTvuu51hjLs5t6Eswdk20= +=ecKh +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:04.arm64.asc b/website/static/security/advisories/FreeBSD-EN-26:04.arm64.asc new file mode 100644 index 0000000000..a7f6e08e82 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:04.arm64.asc @@ -0,0 +1,137 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:04.arm64 Errata Notice + The FreeBSD Project + +Topic: Kernel panic when dumping process core on arm64 + +Category: core +Module: arm64 +Announced: 2026-02-10 +Affects: FreeBSD 15.0 +Corrected: 2026-02-09 16:28:38 UTC (stable/15, 15.0-STABLE) + 2026-02-10 17:56:09 UTC (releng/15.0, 15.0-RELEASE-p3) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +Scalable Vector Extension (SVE) is an extension of the arm64 instruction set +providing SIMD functionality. + +II. Problem Description + +When dumping a process core, if SVE is enabled, the kernel will include an ELF +note in the coredump containing the process' SVE register contents. The +implementation first checks to see if the process has SVE enabled, as part of +pre-calculcating the size of the core dump notes, then checks a second time +when actually populating the note. + +III. Impact + +The bug could cause a kernel panic. + +IV. Workaround + +No workaround is available. Non-arm64 systems are not affected, and arm64 +systems without SVE are not affected. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for an erratum fix" + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for an erratum fix" + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:04/arm64.patch +# fetch https://security.FreeBSD.org/patches/EN-26:04/arm64.patch.asc +# gpg --verify arm64.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ c70a68bbdbf6 stable/15-n282182 +releng/15.0/ 539bbdbd3b0c releng/15.0-n281006 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=292195> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:04.arm64.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmLdYkACgkQbljekB8A +Gu9GDxAAr/APqA0OICssli9j4S+QB6rIeuBjXMIvMqpbUHC2s8Sk3lT75QusaXet +yAeXatOXfUyfYgdggyAomUBIelpLB9u6UmSroaxt/qTOXBx3a8fyvA5h8PR9dIoc +4CjVNYFt4TyiGvowt+ZxxrnC90v/rWKbS/b3SRAMHoUKdImMIrBd1JAcYj0nvLdK +GduJ/GE85NhYjXExdSMtE56rFuHoMihFDgDSXgkxyXKjWlVaPyBzBzStucaw9KIl +b/BuyoKG/Q6vEB1Hv5cgWOnZC9wx6vqZ4OsrLKB9eTZFaBnWFMVLizUVx3PlAdv0 +a1wbrLTqKYmspUn4mIphLVorIuOGED1Rq3HjBGyvZ5sDzqluFqvHUhGfQMam0L8z +BUgcfBROAollz6VK2fUu1y6gVPPD7FkFeINIn6iyFrHc6TjF4pIqrSq5jra53nCA +0tdqu+wiqSyZBRwpqKkLyxDrGLywWeZxqQ3PweLaxhgAbgt72qvxq+NRrBvz1hgU +AioF6hRXwgGgKTadcTd6ffvXsES3EfN8sjJSwAjfyUf6KyAsm0caFkIBctcBsX+M +AadadpYTh9NnVzNz1DvPi1BR1RRnUmaiJLUKBlQsWjDJ+Hrk+jHFXSAlOfZqLUlj +sZmUOGDjW7nuu97aa7oeYaYQXQE/cN3IIlzqoZ+dg+jRv2v5dZ4= +=lHox +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:05.vm.asc b/website/static/security/advisories/FreeBSD-EN-26:05.vm.asc new file mode 100644 index 0000000000..449b58b25b --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:05.vm.asc @@ -0,0 +1,158 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:05.vm Errata Notice + The FreeBSD Project + +Topic: The page fault handler fails to zero memory + +Category: core +Module: vm +Announced: 2026-04-21 +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-13 10:57:44 UTC (stable/15, 15.0-STABLE) + 2026-04-21 15:44:24 UTC (releng/15.0, 15.0-RELEASE-p6) + 2026-04-13 02:56:40 UTC (stable/14, 14.4-STABLE) + 2026-04-21 15:45:29 UTC (releng/14.4, 14.4-RELEASE-p2) + 2026-04-21 15:45:59 UTC (releng/14.3, 14.3-RELEASE-p11) + 2026-04-13 02:58:42 UTC (stable/13, 13.5-STABLE) + 2026-04-21 15:47:06 UTC (releng/13.5, 13.5-RELEASE-p12) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The mmap(2) system call allows applications and system libraries to allocate +heap memory using the MAP_ANON flag. The system call allocates virtual memory +in the calling thread's address space and phyiscal memory is allocated on demand +as page faults occur. Memory allocated this way is allocated to be zero-filled. + +II. Problem Description + +Due to a regression introduced a previous erratum which attempted to fix a +similar problem, under some conditions, particularly heavy memory pressure with +swapping, the phyiscal pages allocated and mapped by the kernel may not be +zero-filled. + +III. Impact + +This bug has been observed to cause process crashes. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot the system. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r now + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r now + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-15.patch +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-15.patch.asc +# gpg --verify vm-15.patch.asc + +[FreeBSD 14.4 and 14.3] +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-14.patch +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-14.patch.asc +# gpg --verify vm-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-13.patch +# fetch https://security.FreeBSD.org/patches/EN-26:05/vm-13.patch.asc +# gpg --verify vm-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 58718cf36593 stable/15-n282974 +releng/15.0/ ffb21713d9fd releng/15.0-n281019 +stable/14/ 9b7c0f4f81f0 stable/14-n273947 +releng/14.4/ 1abe7ead45c3 releng/14.4-n273683 +releng/14.3/ 4d22b3925df8 releng/14.3-n271483 +stable/13/ 50f7b62f0862 stable/13-n259839 +releng/13.5/ 6c9dd7528350 releng/13.5-n259209 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=294039> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:05.vm.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoZoACgkQbljekB8A +Gu+Nvg/+Nac6V7x8ELgRlc0dJfzvEeQgxfcu1acAfpr8Bskew+0c8vjwB1dmBAMp +ENDYyI4+kgVFTG+i6KvFVEISTtlji6VWEul4BBgYow93Auk/S492mvOfaQapnW7V +31hjo0jBrT+ZsBW/inRgjy7QQpukqFiz2+aaXjFs8Q426gmW0SizgOFWinVcWaI1 +/xbp5mQ76VnoPMda5+8VDU4NImqcCTUNsUbsfUGLUjYlFhbVR96BODTYIyxB7lsp ++seXVbnk4SdkRwOVXotoCvi2nhnuVc4P3tmUvpmiuOjRQpvAA43VLbgrQJeZjwad +Xda8vzwScbhHZtkrQ5CqInH+4eSLbPYsz3ST1TGKCMh1GwKzQ1b2hqJ52QKHDYbM +NMl5/PhRcfpQNU2dbJqo2X16weowu4N/fSfMPSZrJE7TBdPqBSK/M1bKk/5nBmga +68PLhPPV/q8MbIaf7+19dGO1vsRiM/XpX0IF4XWwURs+ScQCJom1LXX7bQUv+2N/ +i5iPF+JS+PIUsNgwLBz/oR15nyNpZf6kl+ZAKLlZcHdlW1kFHzDW/4DGcIM1Kvx6 +hpwCYx7othSMy6tSxenOM8DLBx2fvvdtxTE+aSRwgnYjxSFquZkN6iSJZ2TP2LnY +koDdRwMajUcxXXB/+RmaoP3/yqK3v156ilntTmolipfMEocGtnE= +=JBjP +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:06.timerfd.asc b/website/static/security/advisories/FreeBSD-EN-26:06.timerfd.asc new file mode 100644 index 0000000000..2636dc9aa0 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:06.timerfd.asc @@ -0,0 +1,140 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:06.timerfd Errata Notice + The FreeBSD Project + +Topic: Periodic timerfd(2) timers may produce incorrect results + +Category: core +Module: timerfd +Announced: 2026-04-21 +Affects: FreeBSD 14.3 and later. +Corrected: 2026-04-03 15:26:14 UTC (stable/15, 15.0-STABLE) + 2026-04-21 15:44:25 UTC (releng/15.0, 15.0-RELEASE-p6) + 2026-04-03 15:27:26 UTC (stable/14, 14.4-STABLE) + 2026-04-21 15:45:30 UTC (releng/14.4, 14.4-RELEASE-p2) + 2026-04-21 15:46:00 UTC (releng/14.3, 14.3-RELEASE-p11) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The timerfd(2) family of system calls provides a file descriptor-based +interface for managing timers. + +II. Problem Description + +timerfd(2) implements periodic timers. The implementation had a bug which +caused it to fire too early in some cases. + +III. Impact + +The bug has been observed to cause excessive CPU usage in some applications, +particularly in some KDE desktop programs. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot the system. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r now + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r now + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:06/timerfd.patch +# fetch https://security.FreeBSD.org/patches/EN-26:06/timerfd.patch.asc +# gpg --verify timerfd.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 9b785380f307 stable/15-n282826 +releng/15.0/ b0be1af0c48b releng/15.0-n281020 +stable/14/ 3c00f603a280 stable/14-n273878 +releng/14.4/ df8d2f945028 releng/14.4-n273684 +releng/14.3/ f37c6e3a133e releng/14.3-n271484 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=293368> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:06.timerfd.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoZ8ACgkQbljekB8A +Gu9aeRAA28qaGYm351M3YdLLoo6XeT5iklKRCvPPZoIJtoP5V9UPUkW6NFkpYUqp +7sB3VrZ5xPImfCK1o6qE0oT9lnXqQZnGoPyqwoUJwcmRmLY/Js2s1zzn5q7qqdw0 +L/LseIFkvRelhy3KYSO9xnxm/eNQj/A0YK8w/Hi1tM0KR2IBtUjYVMKDvWLrPENH +z+mhlDBOCX1rbSz/E87WAZxZfarBG5XaGIytoBla8IEEsgaARVKr6iYqZaX17ZIZ +u0UgedQ38pQK0QQDhBE26gxwDu+2AZYo0SxdRXnVDkXUOgGkCoiGInyPLVQtrVcb +rmojbUDGDGbwraNkrUZ6wZjKJEArVJ9eC13AROSRc9vAneG3z2i52YaOGURrOZui +7yzj2d0SyglWhlV6sG/rJUAuTV7XB53JqzNyzLFm2tK3tlxOBMOEJp/qm0QG4sL/ +chXc/VIu8VqXeb3MmHtyWrMW+0hoLKI7pBVFdISiefjLRMHVscUZp3Ph7xvZT3GT ++hpvkMz2cp2CSn/N7+qHnEpoP8tgXPEneRPj3MgE0F6pqm3nVx/tAhoUBo9HYBRc +J6zWq5wkyRzIej6OFUM6gT3xRLeNLEODpDyKkcwanh9nvITVB7QbfmmC0E3fUfYM +NSGmlRNwnS9Nsuz0uF5Fj3gxEyhBMkBMfHRqV9rPimHgThrWcLM= +=omqs +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:07.pkgbase.asc b/website/static/security/advisories/FreeBSD-EN-26:07.pkgbase.asc new file mode 100644 index 0000000000..f89f748f26 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:07.pkgbase.asc @@ -0,0 +1,113 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:07.pkgbase Errata Notice + The FreeBSD Project + +Topic: Base packages fail to build with newer versions of libucl + +Category: core +Module: packages +Announced: 2026-04-21 +Affects: FreeBSD 15.0 +Corrected: 2026-04-07 11:27:02 UTC (stable/15, 15.0-STABLE) + 2026-04-21 15:44:26 UTC (releng/15.0, 15.0-RELEASE-p6) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The libucl library is used for parsing documents in the UCL markup format. +The base system private Lua (flua) exposes libucl to Lua applications via +the "ucl" module. + +II. Problem Description + +In libucl version 0.9.3, an API change was made in the Lua ucl module +to prohibit the use of certain syntax by default, specifically the +".include" directive. This change causes the base system package build +("make update-packages") to fail when the host system is using libucl +0.9.3 or later. + +III. Impact + +Future versions of FreeBSD, which include libucl 0.9.3 or later, will +be unable to build FreeBSD 15.0 base system packages from source. + +IV. Workaround + +No workaround is available. + +V. Solution + +Update the base system source tree to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +No action is required on the host (build) system. + +To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:07/pkgbase.patch +# fetch https://security.FreeBSD.org/patches/EN-26:07/pkgbase.patch.asc +# gpg --verify pkgbase.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 976b2ebf4309 stable/15-n282865 +releng/15.0/ f3bbb238daa1 releng/15.0-n281021 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:07.pkgbase.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaEACgkQbljekB8A +Gu9oRhAAog+a+4hJ3OtOel1VVHOgB+JrKfKQHedMitP5RDZAy0e3tWBkm2lKXitv +akZIxFeqmJufBtZRQQSqa9Y9GSFklYHOXh+p/YvObshgkyXijHt+6DtcMtQEmryd +ZDSpVxBpmFP/taGHO7KdSOYuhoyaF5zYUzbuh62AlYHWD/48TPCyBWnEBzcPrGXz +Ew3FltDqKwtccACBZyI9VZFUMCTfCQeaOxB41zEhNGAbxu9DAmpD1t3e5kxHr8ji +imFRVwi0CsKvB9JGcU5BXKU1YtmG4hXEl9CvacNwxOFGjONB+MYZCNfdNXA9SDjn +9fRhz1TzVcFN6i4zWgu2YCV8id5YtaFQuYYjLZQczWgtoNKxBhqpEjeNGKTp1YIb +kwCdF+K+bbLPdtOl6w8E7q3Ksm7AluwbtjJaXskABgUYfXTSDlo6N/HHFd8WNRM0 ++u+XZ/DRhpgNVUDlQJU2XhfYKQyGyd3H//ZtD+ExQeMnTQYASBll3t6hhHx5wTWo +ZHpWJ1dUTZfv0vJMcNrIF0H81AgTigA6Saq4OrIYiec/4HBAIs+MeVO0oWCvF0bs +0g67n6+1Kxz29mXi2nWIbFmILZGEYq3J0y+hEJsr8gmRBgmWpFQJBOYUHXnZwYUG +q4YDpXvE9WWKATm/KB3clAd08QQej26P+Qow0ck1Gq17aPWCL6w= +=jKUS +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:08.pf.asc b/website/static/security/advisories/FreeBSD-EN-26:08.pf.asc new file mode 100644 index 0000000000..c5a4f42406 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:08.pf.asc @@ -0,0 +1,139 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:08.pf Errata Notice + The FreeBSD Project + +Topic: Incorrect duplicate rule detection for automatic tables + +Category: core +Module: pf +Announced: 2026-04-29 +Credits: Michael Sinatra +Affects: FreeBSD 15.0 +Corrected: 2026-04-26 10:12:28 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:24 UTC (releng/15.0, 15.0-RELEASE-p7) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +pf is an Internet Protocol packet filter originally written for OpenBSD. +While loading its configuration, pf hashes rules and silently drops +duplicates as an optimisation. Only the first rule with the same hash is +considered. + +II. Problem Description + +While checking for duplicate rules pf did not distinguish automatically +created tables from each other. As a result some of those rules may have +unexpectedly not been loaded. + +III. Impact + +The ruleset loaded in the kernel might not match the configured ruleset. + +IV. Workaround + +This problem only affects rules with tables created by the pfctl rules +optimiser. Either disable ruleset optimisation ('set ruleset-optimization +none'), or avoid constructs which would be optimisised into a table (e.g. by +manually creating such tables). + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot the system. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r now + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r now + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:08/pf.patch +# fetch https://security.FreeBSD.org/patches/EN-26:08/pf.patch.asc +# gpg --verify pf.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ fdcc60f52841 stable/15-n283345 +releng/15.0/ d91d13c12484 releng/15.0-n281025 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:08.pf.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySREbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvIygQAKSJuU4Ka3cRRqje85kA +O03aC+IoU1YOaepkziI4TKxwKNSc7wh4S0xlCBiNXDqM9JUs20XbG47JT1GDUKP9 +TNDymnUxNGjzmgEwbh/ZQvTKGqib2d0c4fhvLWMSg6FAbET8EnkyniM5A55QfUX0 +YwsTFRk27K09AcCW8gpoRgAjJBhdlN18SvvlE8CQ57xpUQnukFJp+zh37OCGkRVO +fciwOmEYmsrIur9vde7RX/ohBX2RbB3QrMQh9x4td+RpwUGfEkZ4oei+aJWJazVW +VimwkJXXSl2Hdn4V/eNPKj3viSu40tgTPQelSgh1qFPxLMTVvRf1I8VlKYTFHV1O +0EGGsya4nE1pEYWL1CWh/9v2BoTiV7OVDEcu1prc9p/5dHv4cDNaaRf5ZMN8f7Sp +S1X1eHY/eJ59ayBCPNShOMTf36hvMuQT9hBXdBArb6MpeGLubWFtGsHkaFZtoBvj +QnpH4uTxeDMTZANqoM3t6QqrwDUEKBn9ai25k/k9a7vqYwrcLUo4WsLauiwhAbz0 +7bmnXUE+gbn5qlX03UFLqANA7OujEjuBxc5+vmlJXK+1CARMcQToDEdMojhkBwbN +xgxGtyol/Pq3MwvGZyKMlQii0xre2sA1Gqv41k4l7oPukU8DRAOFZQ9nDBmIB0NW +s9JLPOImH1NE9iA05ezJk46Q +=7VtI +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:09.tzdata.asc b/website/static/security/advisories/FreeBSD-EN-26:09.tzdata.asc new file mode 100644 index 0000000000..09b3d387db --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:09.tzdata.asc @@ -0,0 +1,179 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:09.tzdata Errata Notice + The FreeBSD Project + +Topic: Timezone database information update + +Category: contrib +Module: zoneinfo +Announced: 2026-04-29 +Affects: All supported versions of FreeBSD. +Corrected: 2026-03-05 01:36:15 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:25 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-03-05 01:33:16 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:38 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:18 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-03-05 01:33:52 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:16 UTC (releng/13.5, 13.5-RELEASE-p13) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The IANA Time Zone Database (often called tz or zoneinfo) contains code and +data that represent the history of local time for many representative +locations around the globe. It is updated periodically to reflect changes +made by political bodies to time zone boundaries, UTC offsets, and +daylight-saving rules. + +FreeBSD releases install the IANA Time Zone Database in /usr/share/zoneinfo. +The tzsetup(8) utility allows the user to specify the default local time +zone. Based on the selected time zone, tzsetup(8) copies one of the files +from /usr/share/zoneinfo to /etc/localtime. A time zone may also be selected +for an individual process by setting its TZ environment variable to a desired +time zone name. + +II. Problem Description + +Several changes to future and past timestamps have been recorded in the IANA +Time Zone Database after previous FreeBSD releases were released. This +affects many users in different parts of the world. Because of these +changes, the data in the zoneinfo files need to be updated. If the local +timezone on the running system is affected, tzsetup(8) needs to be run to +update /etc/localtime. + +III. Impact + +An incorrect time will be displayed on a system configured to use one of the +affected time zones if the /usr/share/zoneinfo and /etc/localtime files are +not updated, and all applications on the system that rely on the system time, +such as cron(8) and syslog(8), will be affected. + +IV. Workaround + +The system administrator can install an updated version of the IANA Time Zone +Database from the misc/zoneinfo port and run tzsetup(8). + +Applications that store and display times in Coordinated Universal Time (UTC) +are not affected. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Please note that some third party software, for instance PHP, Ruby, Java, +Perl and Python, may be using different zoneinfo data sources, in such cases +this software must be updated separately. Software packages that are +installed via binary packages can be upgraded by executing 'pkg upgrade'. + +Following the instructions in this Errata Notice will only update the IANA +Time Zone Database installed in /usr/share/zoneinfo. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 13.5, FreeBSD 14.3, and FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/EN-26:09/tzdata-2026b.patch +# fetch https://security.FreeBSD.org/patches/EN-26:09/tzdata-2026b.patch.asc +# gpg --verify tzdata-2026b.patch.asc + +[FreeBSD 14.4] +# fetch https://security.FreeBSD.org/patches/EN-26:09/tzdata-2026b-144.patch +# fetch https://security.FreeBSD.org/patches/EN-26:09/tzdata-2026b-144.patch.asc +# gpg --verify tzdata-2026b-144.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart all the affected applications and daemons, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 564480f108e7 stable/15-n282573 +releng/15.0/ 183f96697f82 releng/15.0-n281026 +stable/14/ 4830cb713ed8 stable/14-n273807 +releng/14.4/ 677aeab69b13 releng/14.4-n273688 +releng/14.3/ 1d3ca32f88f2 releng/14.3-n271488 +stable/13/ c0b2aff48ff3 stable/13-n259815 +releng/13.5/ f7e6b9f128e3 releng/13.5-n259213 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://github.com/eggert/tz/blob/2026b/NEWS> +<URL:https://github.com/eggert/tz/blob/2026a/NEWS> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:09.tzdata.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRMbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvVGsP/20IASIuyeEzCQSGN/oA +u/t7PXGIHre/ApxXzQ+K2A4Sn92f0VAG+SG4g4zdLAI+kQXfdCGq2b0oJoEzQg64 +fLAMF772Pc9GMijEXcTMU76hVqD9RiQncOH8w5ODWe3Lmszr8y0foFC9LU0IyccC +5MbHIv9vRRIe0Wpgp33XMLU2mjND+4LVgKxGHpqz86Rqo9zjLAbW1aiSK9mJBE5n +BHWWbRpG8lFzm3jx0m7bIZYaghnnuyrg5TV7bZBbMPg64WTFrBrEyS3QlI9addp/ +hwxwUY2F14fyyjgnlVOVNsMX/BaDh/c6W8R/EyFVxADjAQazQqJJxO/DTwlxqnbu +gaiwdn64vPfR9xJgglsaDutvytEXUMcNuNpDWu8OZUWx1Vd+OnJKLu0m6JC0LLuA +LFbq72HyTNoI0I9kpjkY5XBcuPx4DZHzG3WgvgYJ7tO1myUDaKjawAc2khxHsvpf +JIsY85kBBEoqXEJiLb5DHVO+2Airldz/8DlHVUMWmds9QrQVo7bQzwRpFMZDDc3b +Psp0U9FRe87eQLhgwMn9dRi7QHRRcjAfcqOb3HRHMVRZ2MNq0O9vIRGMyfLzOqwn +iweujCGTmSB9tph/StkKv/n+4zzxLOvyJcmSYcz3zLuFq9t2qOeRtQnhD4tn4wLW +Kq2ZK/k/IL4g1lI6rg4C3BmF +=Mc5t +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:10.amd64.asc b/website/static/security/advisories/FreeBSD-EN-26:10.amd64.asc new file mode 100644 index 0000000000..30eff34440 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:10.amd64.asc @@ -0,0 +1,155 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:10.amd64 Errata Notice + The FreeBSD Project + +Topic: TLB invalidation bug on AMD systems with INVLPGB + +Category: core +Module: vm +Announced: 2026-04-29 +Affects: FreeBSD 14.3 and later +Corrected: 2026-04-23 13:48:45 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:26 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-23 13:49:23 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:39 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:19 UTC (releng/14.3, 14.3-RELEASE-p12) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +On multi-core systems, TLB invalidation operations must notify other cores, +as each core maintains a local TLB. On amd64 systems this has historically +been implemented using interprocessor interrupts. Recent AMD CPUs provide +a new instruction, invlpgb, which allows a core to broadcast TLB invalidations +to other cores without need to explicitly raise interrupts. The FreeBSD kernel +makes use of this instruction when available. + +II. Problem Description + +The FreeBSD implementation of ranged TLB invalidation took advantage of a bit +in an invlpgb operand to invalidate consecutive 2M entries, instead of +invalidating purely in increments of 4K pages. The hardware invlpgb +implementation uses the underlying page size to invalidate regardless of the +status of this bit, which may leave a series of 4K mappings intact that should +have been invalidated. + +III. Impact + +Failing to invalidate pages when it required may result in apparent kernel +memory corruption, typically resulting in a kernel panic. Workloads involving +heavy use of kqueue(2) and/or large file descriptor tables seem to trigger +the problem somewhat readily. + +IV. Workaround + +Intel and non-x86 systems are not affected. + +AMD systems that support INVLPGB (reported during the kernel boot process in +"AMD Extended Feature Extensions ID EBX") may set vm.pmap.invlpgb_works=0 in +/boot/loader.conf to work around this issue by disabling the use of invlpgb. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot the system. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:10/amd64.patch +# fetch https://security.FreeBSD.org/patches/EN-26:10/amd64.patch.asc +# gpg --verify amd64.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 280cfe2264d7 stable/15-n283199 +releng/15.0/ 182c59658218 releng/15.0-n281027 +stable/14/ ff11ae166cd9 stable/14-n274021 +releng/14.4/ b00785205990 releng/14.4-n273689 +releng/14.3/ 3b1365cb816e releng/14.3-n271489 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=293382> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:10.amd64.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRcbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrv4zAP/3/9no397tY5+uMITwzb +d8RklxyJatGAYnqSQrJCjxm4er+CUijdCb6jUrg2L2hKt8c3KOQctSY5ko2agkZ2 +41ghOeIOU6N9+aiNN4wlqCbgufUXjtBWBBEgOvJHyU1QnSazKDZmGAwWfiTz8Uh7 +QtuRHV/I8LDKpd6UtVC6S6lsKSiDrmMQ6CmDSMiMDEpJO8cM1rKejU/gGSTaiwak +25SvR6z1rgJwh5VFKnT5a7G9Gw3oV04+zWQRoYOotiblg1qUgLAjMxogrIvFQKbR +fQElldSwQl7ErlFjYCBrvDbXzGqlsDDab05ay4361VD92QWQ4o64X5KHR+Rb0yYt +RWfPxfCNA1fNMDjkY1y9ROjGERuNdhJzGl5o2m6TXJl/rUX+BZrWZLTC/68CMy/B +DHrKPMLRD6rOS6AupNK1UfKoRPqha9tdwdofOOD4qr6PQ0UecLyUrUQljlK6QUYm +yUQQzC0eun6SdQihPaHGEXK0oe7MqWJvt7s82DE6EKKR8FJ2aqWfMT7qjV3Y3E7e +TJzJGDsbLoZYtPl8u6OQM2gaxAf5CqSCxU7PvyOsu5/gf89CsakdC6OUBkXh/pAS +wCLDDyqffmgwOi1hE9ACgUOVASRyrITZwP1sqyAVJF8yY3YhxGHImaFrdAJ/yU4Q +xp9Ok7v2qSxueDnMc9C16AFt +=pWDj +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:11.dhclient.asc b/website/static/security/advisories/FreeBSD-EN-26:11.dhclient.asc new file mode 100644 index 0000000000..153379010a --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:11.dhclient.asc @@ -0,0 +1,156 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:11.dhclient Errata Notice + The FreeBSD Project + +Topic: dhclient(8) lease validation is too strict + +Category: core +Module: dhclient +Announced: 2026-05-01 +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-30 21:07:00 UTC (stable/15, 15.0-STABLE) + 2026-05-01 15:08:46 UTC (releng/15.0, 15.0-RELEASE-p8) + 2026-04-30 21:07:11 UTC (stable/14, 14.4-STABLE) + 2026-05-01 15:08:37 UTC (releng/14.4, 14.4-RELEASE-p4) + 2026-05-01 15:08:30 UTC (releng/14.3, 14.3-RELEASE-p13) + 2026-04-30 21:07:24 UTC (stable/13, 13.5-STABLE) + 2026-05-01 15:08:19 UTC (releng/13.5, 13.5-RELEASE-p14) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +Note: While FreeBSD 13.5 is end of life (EOL) as of May 1st, 2026, the +Security Team has decided to patch this issue as it was identified and a fix +was in-flight before the EOL date. + +I. Background + +dhclient(8) is the default IPv4 DHCP client used on FreeBSD. It is +responsible for contacting DHCP servers on a network segment and for +initialising and configuring network interfaces based on received +information. + +When processing a DHCP offer, dhclient passes various parameters provided by +the server to dhclient-script(8). DHCP options, as documented in +dhcp-options(5), are passed via the environment. + +II. Problem Description + +The patch for FreeBSD-SA-26:15.dhclient introduced some validation of the +boot file DHCP option to prevent unescaped values from being written to the +stored lease file. This validation is overly strict and rejects Windows +paths. + +III. Impact + +The overly strict validation may cause dhclient(8) to reject valid leases. + +IV. Workaround + +No workaround is available. Systems not running dhclient(8) are not +affected. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-26:11/dhclient.patch +# fetch https://security.FreeBSD.org/patches/EN-26:11/dhclient.patch.asc +# gpg --verify dhclient.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart the applicable daemons, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 252f603d1704 stable/15-n283453 +releng/15.0/ dc8762cfb6e2 releng/15.0-n281035 +stable/14/ 2f9478ad42c4 stable/14-n274094 +releng/14.4/ dfcb69cdb07e releng/14.4-n273699 +releng/14.3/ 5bad905eb37f releng/14.3-n271499 +stable/13/ b1ece85741db stable/13-n259871 +releng/13.5/ b362b6b6c8f2 releng/13.5-n259221 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=294886> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:11.dhclient.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiAbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvJnEQAJ8ZYWjGt7iYjMkOZiM1 +I7NLl7RygvIWU25ThAOXlA7zPA7LbS23+nca4QlNdvTVkpcfsCrmxhJYY4ymkZh7 +QuEVDEp20n02S7362S9kCpmp3NDXQvuCPNt8zRel4ek3u/b8/9KCASL1jN+1eSgR +G8ZVWVheRzKgsaYJsDIyX0AjNk41gQk8ASYoWjeIk5F14kFk3ozlfJTrBL2XlOuL +J28P47d5lEgU2x04xLSZF9xQrF1I13XZa8pMtogF3aveTXXVzHDJFZIcppu0uQYY +tp9uvyQ6NnzNPBXWztVCJ+eRdxS4RLp3Dp3U9/3GrqVuCfG8BO7kE5OhcjO0EPVC +lmvXBJLqQnsodEQA0BysAsMxlMcw+n6z0np2DFdFCkyLrPCx3Bm+D/WRLngRcp4s ++FBIgoF+ywUXVwLRkVJeCsQJTNzVhneq8rtcfE6LdJoIgW/oOUyNEJTBpgvhXmz6 +/pmW47cmNY+CFWCXAL/7fLZVX1dYvEpSn+Iqqs8Efr2OFfQqRXZunJXNXnKuMtfT +p82Hl////cHObQSqlI95J5yJmdBzOxlpzHTwSLVTD5SfvAcN3PzN3hRhFFqG8lg5 +HV64Fu1xPqLX1mthTw1Sbng5mTUL+MJ5BN26M+UevYZBi02m5nMUyjWH+D4Bn3RS +gajZ9Z16VPgdlPsNPihqsx7k +=Ro3y +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-EN-26:12.freebsd-update.asc b/website/static/security/advisories/FreeBSD-EN-26:12.freebsd-update.asc new file mode 100644 index 0000000000..45566db5ba --- /dev/null +++ b/website/static/security/advisories/FreeBSD-EN-26:12.freebsd-update.asc @@ -0,0 +1,178 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-26:12.freebsd-update Errata Notice + The FreeBSD Project + +Topic: Source inconsistency between freebsd-update, EN/SAs, and git + +Category: core +Module: freebsd-update +Announced: 2026-05-01 +Affects: All supported versions of FreeBSD. +Corrected: 2026-05-01 15:08:47 UTC (releng/15.0, 15.0-RELEASE-p8) + 2026-05-01 15:08:38 UTC (releng/14.4, 14.4-RELEASE-p4) + 2026-05-01 15:08:31 UTC (releng/14.3, 14.3-RELEASE-p13) + 2026-05-01 15:08:20 UTC (releng/13.5, 13.5-RELEASE-p14) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +Note: While FreeBSD 13.5 is end of life (EOL) as of May 1st, 2026, the +Security Team has decided to patch this issue as it was identified and a fix +was in-flight before the EOL date. + +I. Background + +The FreeBSD Security Team distributes patches for supported releases via the +git version control system, as patches link through errata and advisories, +and through the freebsd-update binary update system. + +Both freebsd-update and the errata/advisories do not directly use the +authoritative git repo but instead rely on individual patch files. + +II. Problem Description + +Due to the manual nature of patch file development and management, there are +instances where either a freebsd-update maintained machine or a patched +source tree from errata/advisories have become out of sync with the +authoritative git repository. + +Specifically, an earlier version of the patch associated with SA-26:11.amd64 +was distributed via freebsd-update. The source patch linked in the advisory +and the source in git were both correct. + +Additionally, patches distributed via freebsd-update and errata/advisories +are occasionally missing test or non-material ancillary files to minimize +patch size and improve compatibility across releases, causing an additional +source of drift from the authoritative git repository. + +Pkgbase is unaffected as it directly builds from the authoritative git +repository. + +III. Impact + +As a result of this drift, the FreeBSD Security Team has changed the +freebsd-update build mechanism to retrieve source directly from the +authoritative git repository. This has caused a binary update to rectify the +SA-26:11.amd64 issue as well as alter a few additional files, such as test +infrastructure and ancillary tooling files, that have been updated in git but +were not distributed via freebsd-update. + +IV. Workaround + +No workaround is available. Systems using pkgbase or building directly from +source obtained from the authoritative git repository are unaffected. + +V. Solution + +Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date and reboot the system. + +Perform one of the following: + +1) If your system is installed from base system packages: + +No update is needed as pkgbase is not affected by this issue. + +2) To update your system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a system update" + +3) To update your system via a source code patch: + +The following patches are only intended to be used for source trees that have +been maintained with patches linked by previous EN/SAs. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-150.patch +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-150.patch.asc +# gpg --verify ensa-150.patch.asc + +[FreeBSD 14.4] +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-144.patch +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-144.patch.asc +# gpg --verify ensa-144.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-143.patch +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-143.patch.asc +# gpg --verify ensa-143.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-135.patch +# fetch https://security.FreeBSD.org/patches/EN-26:12/ensa-135.patch.asc +# gpg --verify ensa-135.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +releng/15.0/ 53054229dcb3 releng/15.0-n281036 +releng/14.4/ 49be56ed6fea releng/14.4-n273700 +releng/14.3/ 4f4b48e8a547 releng/14.3-n271500 +releng/13.5/ 2e6399fe39b3 releng/13.5-n259222 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=270166> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-26:12.freebsd-update.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0yLQbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvPNYQAIXixMavK1HRNgv1kzms +qcAlmg/dd46KZKD7SkgAmlqKfO1wIdpDo5GZhcpKqS0TRorgqi7u9UU8xNsYxyG0 +mD00dY1m65Vy5wE56QOYDFGnVgC4ZkP3it0HUGZf2t7H9kWO7LB8w8v41z+V7HKK +XRaECq4OyCjeFL9e9C1BdztkFSeVyubN+L2ca8q4S6EWq+4tu9ubTaY+P+Xojy0X +1jX42p31ZYoowHNoNPoC6jfNXrHYg2n7TZ3/kcEwCHlENpoFNT7a87RbijoAlvNP +4Y/IsvlvFdpSjxuyT9chKCPiCaMKkb26Zzng8WPcveeQP1T0f6vV7OFCIl+5RlSM +dFAYp3+IgyBfNa2iQ+ANYrVZB6718gBiE3mAweO/3VJDRK0+okxtQoOlonOSOUJd +BEQrurf2nVJC0Ihi82C/Yn8lHT6IGgEWQzpLLJH2Y9A5z9IEDNpT7s6l6SwOgVuT +1C16q9IincGwKi8YuL1v3Xr9D71PaFWj9DNVuIVe6j9nAFgqZuIFOTPObDcnfN6t +n7hiL2UdOIr9bUxl/H8FQoh5nHeDfbzSn0pF1mvkUMANC1/WSQY3ZVmQHOF5D0yV +9snZZTdsk4eZjhXJUGnLIgBVpYNqwTF7Hm3A0/LF4nbTQm2w78XMj/dIJq7lLliH +BHnoS2GbAjlAHemJRTt14Zcm +=Baez +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:01.openssl.asc b/website/static/security/advisories/FreeBSD-SA-26:01.openssl.asc new file mode 100644 index 0000000000..135e849c56 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:01.openssl.asc @@ -0,0 +1,203 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:01.openssl Security Advisory + The FreeBSD Project + +Topic: Multiple vulnerabilities in OpenSSL + +Category: contrib +Module: openssl +Announced: 2026-01-27 +Credits: Aisle Research +Affects: All supported versions of FreeBSD. +Corrected: 2026-01-27 19:14:58 UTC (stable/15, 15.0-STABLE) + 2026-01-27 19:15:49 UTC (releng/15.0, 15.0-RELEASE-p2) + 2026-01-27 19:15:10 UTC (stable/14, 14.3-STABLE) + 2026-01-27 19:16:22 UTC (releng/14.3, 14.3-RELEASE-p8) + 2026-01-27 19:15:19 UTC (stable/13, 13.4-STABLE) + 2026-01-27 19:16:45 UTC (releng/13.5, 13.5-RELEASE-p9) +CVE Name: CVE-2025-11187, CVE-2025-15467, CVE-2025-15468, + CVE-2025-15469, CVE-2025-66199, CVE-2025-68160, + CVE-2025-69418, CVE-2025-69419, CVE-2025-69420, + CVE-2025-69421, CVE-2026-22795, CVE-2026-22796 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +FreeBSD includes software from the OpenSSL Project. The OpenSSL Project is a +collaborative effort to develop a robust, commercial-grade, full-featured +Open Source toolkit for the Transport Layer Security (TLS) protocol. It is +also a general-purpose cryptography library. + +II. Problem Description + +Multiple issues have been reported as part of this advisory with different +issues affecting different OpenSSL versions and therefore different FreeBSD +versions. Instead of exhaustively listing detailed writeups for each issue, +please see the referenced advisory from OpenSSL. + +Issues affecting FreeBSD 15.0 (OpenSSL 3.5): + CVE-2025-11187 - Improper validation of PBMAC1 parameters in PKCS#12 MAC verification + CVE-2025-15467 - Stack buffer overflow in CMS AuthEnvelopedData parsing + CVE-2025-15468 - NULL dereference in SSL_CIPHER_find() function on unknown cipher ID + CVE-2025-15469 - "openssl dgst" one-shot codepath silently truncates inputs >16MB + CVE-2025-66199 - TLS 1.3 CompressedCertificate excessive memory allocation + CVE-2025-68160 - Heap out-of-bounds write in BIO_f_linebuffer on short writes + CVE-2025-69418 - Unauthenticated/unencrypted trailing bytes with low-level OCB function calls + CVE-2025-69419 - Out of bounds write in PKCS12_get_friendlyname() UTF-8 conversion + CVE-2025-69420 - Missing ASN1_TYPE validation in TS_RESP_verify_response() function + CVE-2025-69421 - NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex function + CVE-2026-22795 - Missing ASN1_TYPE validation in PKCS#12 parsing + CVE-2026-22796 - ASN1_TYPE Type Confusion in the PKCS7_digest_from_attributes() function + +Issues affecting FreeBSD 14.3 (OpenSSL 3.0): + CVE-2025-15467 - Stack buffer overflow in CMS AuthEnvelopedData parsing + CVE-2025-68160 - Heap out-of-bounds write in BIO_f_linebuffer on short writes + CVE-2025-69418 - Unauthenticated/unencrypted trailing bytes with low-level OCB function calls + CVE-2025-69419 - Out of bounds write in PKCS12_get_friendlyname() UTF-8 conversion + CVE-2025-69420 - Missing ASN1_TYPE validation in TS_RESP_verify_response() function + CVE-2025-69421 - NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex function + CVE-2026-22795 - Missing ASN1_TYPE validation in PKCS#12 parsing + CVE-2026-22796 - ASN1_TYPE Type Confusion in the PKCS7_digest_from_attributes() function + +Issues affecting FreeBSD 13.5 (OpenSSL 1.1.1): + CVE-2025-68160 - Heap out-of-bounds write in BIO_f_linebuffer on short writes + CVE-2025-69418 - Unauthenticated/unencrypted trailing bytes with low-level OCB function calls + CVE-2025-69419 - Out of bounds write in PKCS12_get_friendlyname() UTF-8 conversion + CVE-2025-69420 - Missing ASN1_TYPE validation in TS_RESP_verify_response() function + CVE-2025-69421 - NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex function + CVE-2026-22795 - Missing ASN1_TYPE validation in PKCS#12 parsing + CVE-2026-22796 - ASN1_TYPE Type Confusion in the PKCS7_digest_from_attributes() function + +III. Impact + +The issues include improper/missing validation, NULL pointer dereferences, +out-of-bounds writes, incorrect data exposure, input truncation, excessive +memory allocation, and a stack buffer overflow. + +Security impact can be a minimal information disclosure to a potential remote +code execution. See the OpenSSL advisory for specific details. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) +utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-15.patch +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-15.patch.asc +# gpg --verify openssl-15.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-14.patch +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-14.patch.asc +# gpg --verify openssl-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-13.patch +# fetch https://security.FreeBSD.org/patches/SA-26:01/openssl-13.patch.asc +# gpg --verify openssl-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart all daemons that use the library, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 5626e81f1a43 stable/15-n282001 +releng/15.0/ 02f448fe5cc2 releng/15.0-n281004 +stable/14/ ee8d50bfd59e stable/14-n273467 +releng/14.3/ 65c1295c6bb0 releng/14.3-n271466 +stable/13/ 1741502f8d93 stable/13-n259728 +releng/13.5/ 9afc16c4e8a2 releng/13.5-n259198 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://openssl-library.org/news/secadv/20260127.txt> + +<URL:https://www.cve.org/CVERecord?id=CVE-2025-11187> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-15467> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-15468> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-15469> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-66199> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-68160> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-69418> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-69419> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-69420> +<URL:https://www.cve.org/CVERecord?id=CVE-2025-69421> +<URL:https://www.cve.org/CVERecord?id=CVE-2026-22795> +<URL:https://www.cve.org/CVERecord?id=CVE-2026-22796> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:01.openssl.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDQACgkQbljekB8A +Gu/F1g/+LJ7/7CqPRxwRZ3/PCX6aDCnCOtau49/5EsYYRzplz9YdFIOrfXKd9krg +OQy4gRufTAImG+vbVXjNfWD10r7pLVgbrqYjT9uGMPWEHlaMBlZz/d2sM86B8nLa +KfEuiQYYLFCvU8N8JsdF2krZ8RI1wCs+cMSddOgCmDTsPykDIW37wRYYkxwZakG4 +yQ8tJ1yTn07ayuNXvPdYUeyH67HCDXHOedZUBAQXvjYTpYna1XEOIOEptm73TEMp +/+UN4YPSmpAEBqo4sStEcZ4hTesMiP90hUXFH97QN5Hj4rYZQqHuPNgPJL3XLnZD +n/exm89riGa+Pag8Ok4y5uknAN0FtiKN5pIsTiFhmDzyl8maTD+nraQe3yyDai0Y +F8kR/z+ceQv7HtNl9ACSW57a0YSngURzdNH6jK1LyroXg15U55D4M/5oGKZPC0B1 +yg3qjvyHL/RTd1mx+UHNP6FXpZzTGwav1Y859jnD7UVHDJPKvGC1bol0QklgQ2jf +zR4reh7kITU59CB1iMp1qB5N9oIBi1XVEIRYP59p/fqSb4H4WfGMDdpv4GwI4KGB +KsNylKJ+lBIqRy5NyIUaTEScog4RCPbghUdg9hpX9eitB5XIaLDg9qtBhPeYj2/v +mSk9hEDZT/BvxXWrYskBs6vyoT+gNtbHByLBRTdJp/GsDxfntPo= +=G/dg +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:02.jail.asc b/website/static/security/advisories/FreeBSD-SA-26:02.jail.asc new file mode 100644 index 0000000000..1f36df3553 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:02.jail.asc @@ -0,0 +1,150 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:02.jail Security Advisory + The FreeBSD Project + +Topic: Jail escape by a privileged user via nullfs + +Category: core +Module: jail +Announced: 2026-01-27 +Affects: FreeBSD 14.3 and 13.5 +Corrected: 2025-06-30 14:21:28 UTC (stable/14, 14.3-STABLE) + 2026-01-27 19:16:15 UTC (releng/14.3, 14.3-RELEASE-p8) + 2026-01-26 15:51:19 UTC (stable/13, 13.4-STABLE) + 2026-01-27 19:16:37 UTC (releng/13.5, 13.5-RELEASE-p9) +CVE Name: CVE-2025-15547 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +Jails are an operating system virtualization technology which allow +administrators to confine processes within an environment with limited ability +to affect the system outside of that environment. In particular, jailed +processes typically have their filesystem access confined by a chroot-like +mechanism. + +nullfs(4) is a pseudo-filesystem which allows a directory to be mounted at +another point in the filesystem hierarchy. + +II. Problem Description + +By default, jailed processes cannot mount filesystems, including nullfs(4). +However, the allow.mount.nullfs option enables mounting nullfs filesystems, +subject to privilege checks. + +If a privileged user within a jail is able to nullfs-mount directories, a +limitation of the kernel's path lookup logic allows that user to escape the +jail's chroot, yielding access to the full filesystem of the host or parent +jail. + +III. Impact + +In a jail configured to allow nullfs(4) mounts from within the jail, the jailed +root user can escape the jail's filesystem root. + +IV. Workaround + +No workaround is available. Jails not created with the allow.mount.nullfs option +are unaffected. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) +utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:02/jail-14.patch +# fetch https://security.FreeBSD.org/patches/SA-26:02/jail-14.patch.asc +# gpg --verify jail-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:02/jail-13.patch +# fetch https://security.FreeBSD.org/patches/SA-26:02/jail-13.patch.asc +# gpg --verify jail-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/14/ 53963866f708 stable/14-n271804 +releng/14.3/ 193ae464aa36 releng/14.3-n271460 +stable/13/ f0fbaa71a5a2 stable/13-n259726 +releng/13.5/ e87a5dd8054a releng/13.5-n259191 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=262180> + +<URL:https://www.cve.org/CVERecord?id=CVE-2025-15547> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:02.jail.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NVcACgkQbljekB8A +Gu/70A//VWtonOhQP9CeZPUOL41yHUYKOOm9Wf6DkbWqq7aqxcpM5FiGn3Wq84ql +Qy0qpLIXg4KpHD8qjARqQDg2A3J60O1yW2X7WWLRCCDVMsPRe5sNCuwPH88Mzu+x +1VsE9qne25CKJrLcvFsMoO6XfCx6yQ4Qw6uZjyk1DPPIjZfaZYaM9ysAswAo8tsi +7/s+NsFImjN9S6S7q7Z3E+222pOmEkhUKPNaCXoCXTeutiMd+18oxL290xzXs/49 +0NpdOQcX9R+AiA3hJYkrg6YwoxJASc4aXUv7/SKNRdyL9eRiRkt0ta5jsCup3CXw +SIovbhzauXTbv+AliUoAVSXnEK7S0MyUoMM6RG6OPH7JoKf83Sx61P+D8Y1fMYs1 +Gd+g5Nw00Xk3/8hQUSo91K3+A0Lb88QLt+Wc8pzaj7QYfaaYb9DSfyx3U/cjbYiv +sovFZ7D3r0EH5P3n1jkWHQWrV1/u4I7nd/URC0Lz4WUhEfM3X0abaq5q939fpvJU +y37vBlbfw5d139S3C2frPR2sPX6e6K+jXZzjnpLtYF6CsIjfcfWRCRu3pBvWJ24X +/KCJ2AlhGRDcTbYjafzUQMcni4lw5uZ/gpl5SGfbcOTaM1yC0HWmG8W9NaYR79Gn +QtZ+RgQm5wJJAzHX9wQbVTaMoWW5/AbQy2dhDZBjx2rbZmOGBNc= +=SqAm +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:03.blocklistd.asc b/website/static/security/advisories/FreeBSD-SA-26:03.blocklistd.asc new file mode 100644 index 0000000000..fbf716efcd --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:03.blocklistd.asc @@ -0,0 +1,164 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:03.blocklistd Security Advisory + The FreeBSD Project + +Topic: blocklistd(8) socket leak + +Category: core +Module: blocklistd +Announced: 2026-02-10 +Affects: FreeBSD 15.0 +Corrected: 2026-02-10 01:39:29 UTC (stable/15, 15.0-STABLE) + 2026-02-10 17:56:11 UTC (releng/15.0, 15.0-RELEASE-p3) +CVE Name: CVE-2026-2261 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +The blocklistd(8) service keeps a database of IP addresses associated with +certain adverse events reported by other system services, such as failed ssh +logins or emails submitted to non-existent recipients. Once an IP address has +exceeded a configured number of adverse events, blocklistd runs a helper script +which performs a preprogrammed action, usually adding the IP address to a +packet filter blocklist. After a certain amount of time has elapsed, the same +helper script is run again to unblock the address. + +The blocklistd service was previously known as blacklistd and is present under +both names in FreeBSD 15.0-RELEASE. + +II. Problem Description + +Due to a programming error, blocklistd leaks a socket descriptor for each +adverse event report it receives. + +Once a certain number of leaked sockets is reached, blocklistd +becomes unable to run the helper script: a child process is forked, but +this child dereferences a null pointer and crashes before it is able to +exec the helper. At this point, blocklistd still records adverse events +but is unable to block new addresses or unblock addresses whose database +entries have expired. + +Once a second, much higher number of leaked sockets is reached, +blocklistd becomes unable to receive new adverse event reports. + +III. Impact + +An attacker may take advantage of this by triggering a large number of adverse +events from sacrificial IP addresses to effectively disable blocklistd before +launching an attack. + +Even in the absence of attacks or probes by would-be attackers, adverse events +will occur regularly in the course of normal operations, and blocklistd will +gradually run out file descriptors and become ineffective. + +The accumulation of open sockets may have knock-on effects on other parts of +the system, resulting in a general slowdown until blocklistd is restarted. + +IV. Workaround + +The issue can be mitigated to a certain extent by regularly restarting +the blocklistd service. + +However, a determined attacker with access to a sufficiently large pool +of sacrificial IP addresses will be able to disable blocklistd in a +matter of minutes, or hours at most. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:03/blocklistd.patch +# fetch https://security.FreeBSD.org/patches/SA-26:03/blocklistd.patch.asc +# gpg --verify blocklistd.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart the applicable daemons, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 1864a03eb2ac stable/15-n282210 +releng/15.0/ e4781e4e6d88 releng/15.0-n281007 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-2261> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:03.blocklistd.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmLdZIACgkQbljekB8A +Gu849BAAnzXfP+LqpZM2dIPVMma5fHyMKNYSCa3nCS5cBSXgnodaM8KW2W0tuPRA +2NlMU4LUtDng0+UCm3SDVOZRvHL37/2TfaIheCs0QCmLirG78NDweHntEMHQGqUP +vsdQ1kfdkRm1VJyqE8INsSOdlE8YwCywM+HXjEhjv5VNTzzVZOj3cnlNABgrrCq7 +DcKuCZ9uDZRva+X71YRs3n9ZWghSuONB9ycys2YdYG3fp2wEMUpwEsRFjR1oYWOM +JjmlvfXJSeNq4vXd425zX3trLunVEqRVEaLtkl3NDx7/fVAN05MrXx5eB7oTBa5X +9NzFDdQpJZw3Fk7B6cRUZa4v/mPFc2ZrfMKEIrMz+7brVl5InSjvi7ne3ERRujr0 +Db4Kbf9XrAx1NaFXrffU6jmVrhZOz7Z9Y+H+1V7yCYZiShkwz2rrghghcrH3QH0x +2jJXsT+M5lYDA2oFPc0eXPtlidrmCcWHMVM4b8xkZ/tBCaq31F4T7RWXj0QiO44Z +7AlV7ejZquknMA0gNmmOrOMW3kQcCUwJA0SBXcQ7WE5sgnQeXdZcl9wWtSkjYuhr +g1YHde8rNUNcHBC+FPZlru/PsuOrc1/XzdjO4uRpSEK++hOR4ZmLUBThd+u8H9b4 +bA9kCxgNwfuOq9c3hYhFjWme+kxHRLRAdn4un19zLwUvaqLqS0k= +=1MK1 +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:04.jail.asc b/website/static/security/advisories/FreeBSD-SA-26:04.jail.asc new file mode 100644 index 0000000000..92716c237c --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:04.jail.asc @@ -0,0 +1,165 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:04.jail Security Advisory + The FreeBSD Project + +Topic: Jail chroot escape via fd exchange with a different jail + +Category: core +Module: jail +Announced: 2026-02-24 +Affects: FreeBSD 14.3 and 13.5. +Corrected: 2025-07-29 12:49:03 UTC (stable/14, 14.3-STABLE) + 2026-02-24 16:01:32 UTC (releng/14.3, 14.3-RELEASE-p9) + 2026-02-09 20:44:00 UTC (stable/13, 13.4-STABLE) + 2026-02-24 16:04:42 UTC (releng/13.5, 13.5-RELEASE-p10) +CVE Name: CVE-2025-15576 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +Jails are an operating system virtualization technology which allow +administrators to confine processes within an environment with limited ability +to affect the system outside of that environment. In particular, jailed +processes typically have their filesystem access restricted by a chroot-like +mechanism. + +nullfs(4) is a pseudo-filesystem which allows a directory to be mounted at +another point in the filesystem hierarchy. + +unix domain sockets are a mechanism for interprocess communication. They +behave similarly to Internet sockets but are identified by names in the local +filesystem. unix domain sockets allow processes to exchange file descriptors +using control messages. + +II. Problem Description + +If two sibling jails are restricted to separate filesystem trees, which is to +say that neither of the two jail root directories is an ancestor of the other, +jailed processes may nonetheless be able to access a shared directory via a +nullfs mount, if the administrator has configured one. + +In this case, cooperating processes in the two jails may establish a connection +using a unix domain socket and exchange directory descriptors with each other. + +When performing a filesystem name lookup, at each step of the lookup, the +kernel checks whether the lookup would descend below the jail root of the +current process. If the jail root directory is not encountered, the lookup +continues. + +III. Impact + +In a configuration where processes in two different jails are able to exchange +file descriptors using a unix domain socket, it is possible for a jailed +process to receive a directory for a descriptor that is below that process' +jail root. This enables full filesystem access for a jailed process, breaking +the chroot. + +Note that the system administrator is still responsible for ensuring that an +unprivileged user on the jail host is not able to pass directory descriptors +to a jailed process, even in a patched kernel. + +IV. Workaround + +No workaround is available. Note that in order to exploit this problem, an +attacker requires control over processes in two jails which share a nullfs +mount in which a unix socket can be installed. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:04/jail-14.patch +# fetch https://security.FreeBSD.org/patches/SA-26:04/jail-14.patch.asc +# gpg --verify jail-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:04/jail-13.patch +# fetch https://security.FreeBSD.org/patches/SA-26:04/jail-13.patch.asc +# gpg --verify jail-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/14/ 3ad3ab5f9b6e stable/14-n272076 +releng/14.3/ fbc35b3e6615 releng/14.3-n271471 +stable/13/ 73530e4c2ea9 stable/13-n259752 +releng/13.5/ e6b96891ef7c releng/13.5-n259202 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2025-15576> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:04.jail.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmd0NwACgkQbljekB8A +Gu9WrxAAzgjxobnwhy+3RrD4XSOViKv7Dk6va/cqZtiP+SEv1lwM86P4aeUbqCOL +XPGItri1El9gQoBYsLS/b5ODbevV/CBaTeZbGwm129B9xdrJ4lQgQrDBh3qgo55k +OxQTnZbJgnF0YtjcSnkC+oWs4selpADEevEe2ohVUrV4OjXjVoCc3hVibPPwFh+8 +G5lPqcI26kXXimjb+zC+5yFQwNy/an9sYeiVnYceCuAOxxoV0Uf23Z5Ndc5oPBUD +lYMfrfuqmuhX6AtxTSU7x4BDx4MGTDIMYjU/LXptzMI5bpvqUy4F4lqx0t8vXV8F +T8vpbzGt8uhyRoD9Wp9LCIS7PpjBNm3YINY4Zd9z46tiC5ItTSV5mkJzatDB2zW+ +4iMcFQxHFGksHyrGn3epYKm1C3NtbKc5lEVHnKZqg11H2xUtDkTRn8AVcy8a9Bh+ +FDo1+yAb96W5by9UGA7nCdF8xwr9+ea/k6JDDfHxgVsOKzOgXsh7wmJ686kTIT2I +2REIMLY79xs50Lii5EMvN1oSjXxb7+WFphe+XCoH39JDTI3ekg7EpnFHcXLzMaVt +rciDlmPBU8h5A8U8GyI359DbIlha2IY5R2yC/opHUkOq/wBDJUZcL2y41BEH11jb +uFxRavagcRePVrSHSuXOH1vSdmsdrtl/h7HBP83J4X6ZG3nnr90= +=cwB8 +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:05.route.asc b/website/static/security/advisories/FreeBSD-SA-26:05.route.asc new file mode 100644 index 0000000000..9e4edbab24 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:05.route.asc @@ -0,0 +1,161 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:05.route Security Advisory + The FreeBSD Project + +Topic: Local DoS and possible privilege escalation via routing sockets + +Category: core +Module: route +Announced: 2026-02-24 +Credits: Adam Crosser of the Praetorian Labs team +Affects: All supported versions of FreeBSD. +Corrected: 2026-02-24 16:00:26 UTC (stable/15, 15.0-STABLE) + 2026-02-24 16:00:39 UTC (releng/15.0, 15.0-RELEASE-p4) + 2026-02-24 16:00:56 UTC (stable/14, 14.4-STABLE) + 2026-02-24 16:02:31 UTC (releng/14.4, 14.4-RC1) + 2026-02-24 16:01:35 UTC (releng/14.3, 14.3-RELEASE-p9) + 2026-02-24 16:03:17 UTC (stable/13, 13.5-STABLE) + 2026-02-24 16:04:45 UTC (releng/13.5, 13.5-RELEASE-p10) +CVE Name: CVE-2026-3038 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +The routing socket interface, route(4), lets users query the state of the +kernel's routing tables. Most routing socket operations require root +privileges, but unprivileged users may send RTM_GET messages to obtain +information about routing table entries. + +II. Problem Description + +The rtsock_msg_buffer() function serializes routing information into a buffer. +As a part of this, it copies sockaddr structures into a sockaddr_storage +structure on the stack. It assumes that the source sockaddr length field had +already been validated, but this is not necessarily the case, and it's possible +for a malicious userspace program to craft a request which triggers a 127-byte +overflow. + +In practice, this overflow immediately overwrites the canary for the +rtsock_msg_buffer() stack frame, resulting in a panic once the function +returns. + +III. Impact + +The bug allows an unprivileged user to crash the kernel by triggering a stack +buffer overflow in rtsock_msg_buffer(). In particular, the overflow will +corrupt a stack canary value that is verified when the function returns; this +mitigates the impact of the stack overflow by triggering a kernel panic. + +Other kernel bugs may exist which allow userspace to find the canary value and +thus defeat the mitigation, at which point local privilege escalation may be +possible. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:05/route.patch +# fetch https://security.FreeBSD.org/patches/SA-26:05/route.patch.asc +# gpg --verify route.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ df932377e7dd stable/15-n282455 +releng/15.0/ 5de6a55c70ba releng/15.0-n281009 +stable/14/ 1eb2beb3686c stable/14-n273785 +releng/14.4/ 7465d0b094b7 releng/14.4-n273667 +releng/14.3/ d521badafdaa releng/14.3-n271474 +stable/13/ 8b476ffc4ea3 stable/13-n259798 +releng/13.5/ c2e2bfbd9e09 releng/13.5-n259205 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-3038> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:05.route.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmdz7cACgkQbljekB8A +Gu+9ehAAziBGPEv4RtXdh5OPqRkmJrZbxYNsiDmsqCO1alaEq/P64uLSI3ShOEf7 +K51oW4P+pukw13mJ7koDfWIFcJ5Jr4p+4vPIUenHafgXzOB9i6prn9kF0RFJN9zX +ziUaz8DGKd7B01eUoFj0p5l6rm00Z8q9l47ePOXfa+CS90lZxV/9z55UbmmCioQv +Ar98kPvaRmrmUqifuj72Jh1Wf69XLMDv4CI7BRumXIQnrHJ1xco4T9hHrHzPyNCf +cObfVsYMew/OGL2WgqfWvOEbmmC4mSW080kjPNmJxA+WG5fc0xQWaF41Kq1YDSWD +23SLqgjzTEP7zcsN/bW1k/7maf7lkKUWjtC/sjcqJRPfgWfHjDCVcMTKSjje65ld +Ml4sw4Ea2+jbOZqNcQhtFLo69atTu3oOgN2Gc677rvpkLl+HSivrX7D/1ULYfE0x +TbtW8Y8fqyNaPPOc1PktUcvQsZ1Sq8OKghOd/JAv1sKLZnxs61fWEMJKTJZEMHQB +NOnvw8PO2JPNMgJhPJz1CuD0pUCyTDqHYvfEI6TQikJmqKfrhAOBl8ccfNMyMmje +ZPW1f6hXud7c11OQXJ/u3QyBe7E+3v9MOf7Tn/mbFviwMx/xmG2VbgAuBBOVx6qb +QnHv9Ce+szmMV+9i0dj5KlsxhuFfUaDIIc9+iZ/1k8GkjkizDjE= +=V8QD +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:06.tcp.asc b/website/static/security/advisories/FreeBSD-SA-26:06.tcp.asc new file mode 100644 index 0000000000..ae57cc80a2 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:06.tcp.asc @@ -0,0 +1,180 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:06.tcp Security Advisory + The FreeBSD Project + +Topic: TCP: remotely exploitable DoS vector (mbuf leak) + +Category: core +Module: tcp +Announced: 2026-03-26 +Credits: Michael Tuexen (Netflix) +Affects: FreeBSD 14.x and FreeBSD 15.0 +Corrected: 2026-03-26 01:25:22 UTC (stable/15, 15.0-STABLE) + 2026-03-26 01:11:18 UTC (releng/15.0, 15.0-RELEASE-p5) + 2026-03-26 01:28:46 UTC (stable/14, 14.4-STABLE) + 2026-03-26 01:14:54 UTC (releng/14.4, 14.4-RELEASE-p1) + 2026-03-26 01:16:00 UTC (releng/14.3, 14.3-RELEASE-p10) +CVE Name: CVE-2026-4247 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +The Transmission Control Protocol (TCP) is a connection oriented transport +protocol, which can be used as an upper layer of IP. + +When unexpected TCP segments are received for an established TCP connection, +so called "challenge ACK" segments may be sent back in response if certain +criteria are met. + +Challenge ACKs are rate limited to ensure the remote peer does not waste too +many CPU cycles or outbound bandwidth on the local peer if large numbers of +unexpected TCP segments are received. + +The rate limiting is controlled by the net.inet.tcp.ack_war_timewindow and +net.inet.tcp.ack_war_cnt sysctls which default to 1000 (milliseconds) and 5 +respectively i.e. challenge ACKs will be sent for the first 5 qualifying TCP +segments received within a 1s time period and the rest will be ignored. + +The handling of challenge ACKs is common code in tcp_subr.c shared among the +different TCP stacks available in the system. This includes the FreeBSD +default, RACK and BBR stacks. There are differences in the behaviour of the +different stacks; e.g. the base FreeBSD stack sends challenge ACKs to a larger +set of unexpected packets. + +II. Problem Description + +When a challenge ACK is to be sent tcp_respond() constructs and sends the +challenge ACK and consumes the mbuf that is passed in. When no challenge ACK +should be sent the function returns and leaks the mbuf. + +III. Impact + +If an attacker is either on path with an established TCP connection, or can +themselves establish a TCP connection, to an affected FreeBSD machine, they +can easily craft and send packets which meet the challenge ACK criteria and +cause the FreeBSD host to leak an mbuf for each crafted packet in excess of +the configured rate limit settings i.e. with default settings, crafted packets +in excess of the first 5 sent within a 1s period will leak an mbuf. + +Technically, off-path attackers can also exploit this problem by guessing the +IP addresses, TCP port numbers and in some cases the sequence numbers of +established connections and spoofing packets towards a FreeBSD machine, but +this is harder to do effectively. + +IV. Workaround + +The mbuf leak can be mitigated by not rate limiting the sending of challenge +ACKs. This can be achieved with immediate effect by setting the +net.inet.tcp.ack_war_timewindow sysctl to 0: + +sysctl net.inet.tcp.ack_war_timewindow=0 + +This mitigation does trade off the leaking of mbufs against additional +CPU/resource cost associated with responding to all challenge ACK eligible +packets received for established TCP connections. + +To make this change persistent across reboots, add it to /etc/sysctl.conf. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or release / +security branch (releng) dated after the correction date and reboot. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +which were not installed using base system packages, can be updated via the +freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:06/tcp.patch +# fetch https://security.FreeBSD.org/patches/SA-26:06/tcp.patch.asc +# gpg --verify tcp.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 1fddb5435315 stable/15-n282699 +releng/15.0/ de9e5d82581e releng/15.0-n281011 +stable/14/ b45e7530ffb9 stable/14-n273839 +releng/14.4/ 44dd8b58394b releng/14.4-n273676 +releng/14.3/ a9cba5321021 releng/14.3-n271476 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-4247> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:06.tcp.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkVIACgkQbljekB8A +Gu/sWRAAtGouQg2M2RuF4+EFK1fpDKyDgBpbx88kH/y2ToHQ/voEwpeC3OOulfQ0 +kM7vluUY2yf/yITXJnX/czqxX4flpC9fsAIZtSjXwI27V+xrvWwz/LTgmBumJjgC +VI0i66c6ajie8JC6h4Q2yYpF7M2ymYo/rLXXFM+nq/UpOWLEXbEzzDv6hwvwYqJd +h7pvoNUDWRjbxHykilUQ+KrnEDRz4cdmulil+1aAS1af2WHdROHfOSsVmSY/hQJh +MPA9dJxESzHAjYhjQrLFoWiuSt1JFOt5k/Y6FI4ix1UElJVEvwF7NEj6VxTW9/UX +0sWGmKt23ckfBG6fwBjW2e9NVnqIU4NNMbR0vJghtVsi0K4uw4b5/9n2WbfYYHQZ +eoZ8BiFRdrbRwFgk7NK9UG5r1B0l7O9rJWob0ZUt2/tGYpC7sLz9kOWAptD7JPpE +XkrK354K0KIBPdoVj7QDsK7njYkvnjxlHwWX148gQ1maEX/zWHD6x5RXS+QShzjL +kmp/h5Eiz977qHzotXkK7Le/4EnHQlLYO7n8NafoRrCRszPPlLv1/gaEHYYlTU+S +GMJpvsV9ENd15BhcZRCoLRxwa94D9beDhw89RTgPZ8ItpRO7z1cCfZrNC4aE0x3P +Q+BVMF18lrU/UB4jDW2/BmoGdZSjJMqxHaDGiHZZewQX/dVP2BU= +=a5LJ +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:07.nvmf.asc b/website/static/security/advisories/FreeBSD-SA-26:07.nvmf.asc new file mode 100644 index 0000000000..af5c8618bb --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:07.nvmf.asc @@ -0,0 +1,140 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:07.nvmf Security Advisory + The FreeBSD Project + +Topic: Remote denial of service via null pointer dereference + +Category: core +Module: nvmf +Announced: 2026-03-26 +Credits: Nikolay Denev <ndenev@gmail.com> +Affects: FreeBSD 15.0 +Corrected: 2026-03-25 01:29:47 UTC (stable/15, 15.0-STABLE) + 2026-03-26 01:11:19 UTC (releng/15.0, 15.0-RELEASE-p5) +CVE Name: CVE-2026-4652 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +The nvmf driver implements the kernel component of an NVMe over Fabrics +host. + +The CONNECT command is used to create connections (queue pairs) that +carry NVMe read/write commands over the network. For I/O queues, this +is commonly referred to as an I/O CONNECT. + +II. Problem Description + +On a system exposing an NVMe/TCP target, a remote client can trigger +a kernel panic by sending a CONNECT command for an I/O queue with a +bogus or stale CNTLID. + +III. Impact + +An attacker with network access to the NVMe/TCP target can trigger +an unauthenticated Denial of Service condition on the affected machine. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or release / +security branch (releng) dated after the correction date and reboot. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +which were not installed using base system packages, can be updated via the +freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:07/nvmf.patch +# fetch https://security.FreeBSD.org/patches/SA-26:07/nvmf.patch.asc +# gpg --verify nvmf.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ b1d32521747f stable/15-n282694 +releng/15.0/ 48766013063a releng/15.0-n281012 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-4652> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:07.nvmf.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkV4ACgkQbljekB8A +Gu/KVBAA0QPwISRLuInGilUGPkO0fjXD5teeufdqHOABQJB+YgvelArfgd0odN4S +b7OXiDIdUsJsJF5CDFm5FVkAuQe0PnhakuXnxEMrDxpNu+H9zFBWrmCVtflWRay3 +APB3EGqxghhez/pNx+8M/Tf//QZjOmZSsu2C3om7mfv5jGetjRY/3jLkWiMx7ASu +lVFYue+PRSKf0jl0fjsxjvJMosTtgmM6xkB2cpDF+z6HKK6rtt0YUhw+/v0plLxa +jBQNIT3MCJ8OJU75LB5K/84iF3c/PTFupZQIMenejPt1FfC55CDKmta88LGUPxRn +u67tyidS+C7BLMnOn3mlgx3Vst1NxLc5to7KVYr1S3V17na5jglnnE3Av2lE/CMJ +v9UT7IsLG5AsHusY1iYvkiReLfJgeouOlSJkQoiVfJYuT5G0ERdC+Sp3G9X0q8sp +2Q/YA0+qt0Fqdc8hn25Qus1pvWSvg+RBUuDDLsWsC9FbUbyjBNB2Og34dmW46t38 +EWoCFHZ0u/PRPZ7YnwpIE6xx6mDOc7XcVtK9fFc6VKjtiP7sDk42W5O2wyAKBcRl +oTZl56h/g+Kutmnvj1vHAcntX4IbTfXw7S5SVnzPBVD2W6yOKas5R1GBK9O2S4IE +CU69VbcPD51vJY/mY8w6oefZXLoxHE2WH0eAwz3/NJaFRwtqT1k= +=l61h +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc b/website/static/security/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc new file mode 100644 index 0000000000..d312246c4e --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc @@ -0,0 +1,163 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:08.rpcsec_gss Security Advisory + The FreeBSD Project + +Topic: Remote code execution via RPCSEC_GSS packet validation + +Category: core +Module: rpcsec_gss +Announced: 2026-03-26 +Credits: Nicholas Carlini using Claude, Anthropic +Affects: All supported versions of FreeBSD. +Corrected: 2026-03-26 01:25:23 UTC (stable/15, 15.0-STABLE) + 2026-03-26 01:11:20 UTC (releng/15.0, 15.0-RELEASE-p5) + 2026-03-26 01:28:47 UTC (stable/14, 14.4-STABLE) + 2026-03-26 01:14:55 UTC (releng/14.4, 14.4-RELEASE-p1) + 2026-03-26 01:16:01 UTC (releng/14.3, 14.3-RELEASE-p10) + 2026-03-26 01:30:12 UTC (stable/13, 13.5-STABLE) + 2026-03-26 01:34:10 UTC (releng/13.5, 13.5-RELEASE-p11) +CVE Name: CVE-2026-4747 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +Generic Security Services (GSS) is an API which lets applications establish a +private, authenticated communication channel with a server, such as an NFC +server. + +RPCSEC_GSS is a module which enables the use of GSS with Sun RPC (rpc(3)) +servers. It is implemented in the kernel by the kgssapi.ko kernel module, and +used by the NFS server to enable Kerberos-based authentication and encryption +of traffic between the server and clients. In userspace it is implemented by +the librpcsec_gss library. + +II. Problem Description + +Each RPCSEC_GSS data packet is validated by a routine which checks a signature +in the packet. This routine copies a portion of the packet into a stack buffer, +but fails to ensure that the buffer is sufficiently large, and a malicious +client can trigger a stack overflow. Notably, this does not require the client +to authenticate itself first. + +III. Impact + +As kgssapi.ko's RPCSEC_GSS implementation is vulnerable, remote code execution +in the kernel is possible by an authenticated user that is able to send packets +to the kernel's NFS server while kgssapi.ko is loaded into the kernel. + +In userspace, applications which have librpcgss_sec loaded and run an RPC server +are vulnerable to remote code execution from any client able to send it packets. +We are not aware of any such applications in the FreeBSD base system. + +IV. Workaround + +No workaround is available. Kernels that do not have kgssapi.ko loaded are not +vulnerable. In userspace, any daemon linked with librpcgss_sec and running an +RPC server is vulnerable. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:08/rpcsec_gss.patch +# fetch https://security.FreeBSD.org/patches/SA-26:08/rpcsec_gss.patch.asc +# gpg --verify rpcsec_gss.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel and the operating system as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and +<URL:https://www.FreeBSD.org/handbook/makeworld.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 1b00fdc1f3cd stable/15-n282700 +releng/15.0/ 4ec1b6213463 releng/15.0-n281013 +stable/14/ e5ed09ffd592 stable/14-n273840 +releng/14.4/ 7ea03a4238e8 releng/14.4-n273677 +releng/14.3/ b6ce88ab9a5f releng/14.3-n271477 +stable/13/ 99ec7f9b9e48 stable/13-n259823 +releng/13.5/ c4f53a1adbd4 releng/13.5-n259207 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-4747> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkWEACgkQbljekB8A +Gu/LsA/9EC3I0xFSAJpbHLVpV4dmCpzhMUn5CU3iJhXOsV4hWip6fJvjHmiRcVDC +luJ/udrLS6izmx4dmZBcEQMSOt2hXK/P/5JgVQCM0f3hXfkLFWGPnA1/wG4hSqjd +nsbHfExgqs4ToWhgfQDaEwgc5d9FQfnQUTk3noXal1FA6o10+9PAA5nmj74ZGtYC +6umspzzJNR8+6EaTftY8nb40DMAAyNMTBu3S2KikiuiqLSuMETyGEHS0ceMZzX0C +D8rWRlaXpNOyVrRPhEuVurF9SB9EghEB1K587Xm0cqpCLT8GsW5FeSkp4VD2Ir0v +7Ghu693vLbmVwm5pQUNr8cf7uO/kLg6Gce3FWlqYteRN+PeuOkx2DRAChm4QMEK2 +8Xjix/bS3HT6GkRmHCtwS7IU8L1vw/kAt4uvSV5uyEzRbpGKEbrdZOXFUSjPrY3R +xHAKGosZaZKYJ4rveQOhsS1OoevN7ghhEJJ6PJf1wdYOSwNl41zq8R9LVqos4A+w +fJmIQwoSMPhT7E+XCjrsOrt5TuBHrv5O7871IFxk00rsgJN3W2vTw4epEwRiWpJm +mqv40zoarV4L4Gq3P4PAT8VaiWXTo44qyvu9LV+fnEArtlyfYPNLglC7NJKaeI1D +Ou89dG/+L1GeJlkIVbRj4DUfcpLO0yV1LG/KYvQqr4TCILaddzk= +=K+Bc +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:09.pf.asc b/website/static/security/advisories/FreeBSD-SA-26:09.pf.asc new file mode 100644 index 0000000000..13cdb6bd52 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:09.pf.asc @@ -0,0 +1,168 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:09.pf Security Advisory + The FreeBSD Project + +Topic: pf silently ignores certain rules + +Category: core +Module: pf +Announced: 2026-03-25 +Credits: Michael Gmelin +Affects: FreeBSD 14.x and FreeBSD 15.0 +Corrected: 2026-03-25 07:11:58 UTC (stable/15, 15.0-STABLE) + 2026-03-26 01:11:25 UTC (releng/15.0, 15.0-RELEASE-p5) + 2026-03-25 09:58:28 UTC (stable/14, 14.4-STABLE) + 2026-03-26 01:15:00 UTC (releng/14.4, 14.4-RELEASE-p1) + 2026-03-26 01:16:06 UTC (releng/14.3, 14.3-RELEASE-p10) +CVE Name: CVE-2026-4748 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +pf is an Internet Protocol packet filter originally written for OpenBSD. +While loading its configuration, pf hashes rules and silently drops +duplicates as an optimisation. Only the first rule with the same hash is +considered. + +II. Problem Description + +A regression in the way hashes were calculated caused rules containing the +address range syntax (x.x.x.x - y.y.y.y) that only differ in the address +range(s) involved to be silently dropped as duplicates. Only the first of +such rules is actually loaded into pf. Ranges expressed using the +address[/mask-bits] syntax were not affected. + +Some keywords representing actions taken on a packet-matching rule, such as +'log', 'return tll', or 'dnpipe', may suffer from the same issue. It is +unlikely that users have such configurations, as these rules would always be +redundant. The verification described in "IV. Workaround" below will find +these as well. + +III. Impact + +Affected rules are silently ignored, which can lead to unexpected behaviour +including over- and underblocking. + +IV. Workaround + +Only systems using the pf firewall are affected. + +The operator can determine if a specific system is affected by reloading the +configuration verbosely: + +# pfctl -vf /etc/pf.conf | grep already + +As a workaround, affected rules can be rewritten, e.g., by +using tables or multiple rules instead of address ranges. +Another option is to add labels to rules to make them unique. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date +and reboot. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/SA-26:09/pf-15.patch +# fetch https://security.FreeBSD.org/patches/SA-26:09/pf-15.patch.asc +# gpg --verify pf-15.patch.asc + +[FreeBSD 14.x] +# fetch https://security.FreeBSD.org/patches/SA-26:09/pf-14.patch +# fetch https://security.FreeBSD.org/patches/SA-26:09/pf-14.patch.asc +# gpg --verify pf-14.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 4311217a039c stable/15-n282698 +releng/15.0/ d91cf52e31ac releng/15.0-n281017 +stable/14/ e3b801edded9 stable/14-n273835 +releng/14.4/ b6865bca4ba5 releng/14.4-n273681 +releng/14.3/ c03577d99d2d releng/14.3-n271481 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-4748> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:09.pf.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEp+AACgkQbljekB8A +Gu84/Q//cIBdAEmzD04kjglaG1X75rULWJ0fsD26RW89Y3IEvLnUa5yoWV0dKUeW +wRta0n7cvpkLiuDVqSfasVrkVM0EZ70toWcd0JXTRwaJ+i7IhHMByXjvSwTzhS/d +OL2uDzjJ1nUyUqangNM+99Mpr3UQOEIMY9Scq5E0NNr/x6NdWXN4psiB/RCSFU64 +abRos56CPkWbfVQLVZ3i2FihGhYQ2JLnqvP9DgCT6xy6MU5uTDWF57sxe4ciYWGw +4ZRydr/oyTkpthetm9xPFoFkaBiOiGfdTnsOi58f7mcWln+AgiKLzT0KdOd6XkEy +RH22v4254P4nquDXfBTIJUVyDFd8SVIk7Ol78BzRNdEYOEog6KEI3fTjArFMIiy6 +CLPS92ph3xq4aBWMdxnZ4cvfW7Ktm8Zp9xrXCvdRaUGfl+wawzjfjgw62eXaec4x +pFxip2jLziZUDAvpzg1ywK0ajJE+RYh7HlT7CG2pTEcCaaIC0rJ7B2eEIaoO48Ho +Uez92JN54P7xBRLy/rLVfUHz7Td11toAg6wwBTEAQPKssDHh1DQZMLSDKZcGanlt +waUCybHeaWkMZvoHtLlEJjZ8hL/67Ivz2Huv5KCZ5CtpoEqe5ZHmGGS3iOCiuLvQ +9k2F3fkJN4w1zpGHE48JJ03FYQA7cTHwEro7TCRzeM6+KnqgAzE= +=cGmd +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:10.tty.asc b/website/static/security/advisories/FreeBSD-SA-26:10.tty.asc new file mode 100644 index 0000000000..42488b11cb --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:10.tty.asc @@ -0,0 +1,165 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:10.tty Security Advisory + The FreeBSD Project + +Topic: Kernel use-after-free bug in the TIOCNOTTY handler + +Category: core +Module: tty +Announced: 2026-04-21 +Credits: Nicholas Carlini using Claude, Anthropic +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-21 15:43:02 UTC (stable/15, 15.0-STABLE) + 2026-04-21 15:44:27 UTC (releng/15.0, 15.0-RELEASE-p6) + 2026-04-21 15:43:13 UTC (stable/14, 14.4-STABLE) + 2026-04-21 15:45:31 UTC (releng/14.4, 14.4-RELEASE-p2) + 2026-04-21 15:46:01 UTC (releng/14.3, 14.3-RELEASE-p11) + 2026-04-21 15:43:56 UTC (stable/13, 13.5-STABLE) + 2026-04-21 15:47:07 UTC (releng/13.5, 13.5-RELEASE-p12) +CVE Name: CVE-2026-5398 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +TIOCNOTTY is an ioctl(2) operation which allows a process to detach itself +from its controlling terminal. Unprivileged processes may use this ioctl. +See the tty(4) manual page for more information on its usage. + +II. Problem Description + +The implementation of TIOCNOTTY failed to clear a back-pointer from the +structure representing the controlling terminal to the calling process' +session. If the invoking process then exits, the terminal structure +may end up containing a pointer to freed memory. + +III. Impact + +A malicious process can abuse the dangling pointer to grant itself root +privileges. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date, +and reboot the system. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-15.patch +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-15.patch.asc +# gpg --verify tty-15.patch.asc + +[FreeBSD 14.4] +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-14.4.patch +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-14.4.patch.asc +# gpg --verify tty-14.4.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-14.3.patch +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-14.3.patch.asc +# gpg --verify tty-14.3.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-13.patch +# fetch https://security.FreeBSD.org/patches/SA-26:10/tty-13.patch.asc +# gpg --verify tty-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 0c6b1e0864b8 stable/15-n283065 +releng/15.0/ fdee312d0c97 releng/15.0-n281022 +stable/14/ f46210a7ab32 stable/14-n273997 +releng/14.4/ af294329c57f releng/14.4-n273685 +releng/14.3/ 44077c07f19f releng/14.3-n271485 +stable/13/ 5eae7f23fe0e stable/13-n259845 +releng/13.5/ 2862a33bdd1c releng/13.5-n259210 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-5398> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:10.tty.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaMACgkQbljekB8A +Gu8qzA//fuGHRB8Y+n+EUyAGycr0PGMeG423hykkYBAvfBJJP5RYv4Ter79YAeuu +zqXqijjr+yyKcE1+km63/koxUXZmkbpR2Xt/0i2d3jAqnrUioZqwc+llCgqhh6Dr +AhyDn+xCtCWJow0Iktlk6ZHEuQLX6kwGxT/1cvmcnhZE8XQf2PNEbRk8oit+kf8c +LQZF2EBK4wPh5Lik8DvqoyX1k7B44jVhL2AMqs/2fRdTFluY/MIgvbRsRdCQRLJE +doXA2YdDljkTJpAPIg31WP6C7L0LPkeyRm4Xn3zBt4SalyiChfQ9kQYcdQS7/lt4 +LUyrQKQHVtVx2SseYFTtPoncYl2IEmaHOAZkQrfzxFybYryoq4macGbuNZh0Aygq +mpIAIIDKAyKQCcDGzluRL4ksoPyw9Kav7SJJ83P9khrKINaNg5NZc1Ptc7K/UvSk +H5XKwHBaURcXGzl1crBtqbbK5lEvO/UaxXraMwqCTM+WqF7dND2KvSbZEma/FJ8l +7Wcszs2dvgC2dQghlmRlxxYvMGzf49XO4+Y64WarMqmLTAyDV9nBrZGMUj1M2nqC +rgylEscbOn8z/Yq8vpr0sydYRVDBHtVMOaztsqFylGnzRfSjQQH3yuJ40ngvy9yo +GexBhYXFyrruuuuz9p9xplIRzVkHVjkrm9/zwe4bSBylQ+/MeGQ= +=crMa +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:11.amd64.asc b/website/static/security/advisories/FreeBSD-SA-26:11.amd64.asc new file mode 100644 index 0000000000..99e84cbf24 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:11.amd64.asc @@ -0,0 +1,163 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:11.amd64 Security Advisory + The FreeBSD Project + +Topic: Missing large page handling in pmap_pkru_update_range() + +Category: core +Module: amd64 +Announced: 2026-04-21 +Credits: Nicholas Carlini using Claude, Anthropic +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-21 15:43:03 UTC (stable/15, 15.0-STABLE) + 2026-04-21 15:44:28 UTC (releng/15.0, 15.0-RELEASE-p6) + 2026-04-21 15:43:14 UTC (stable/14, 14.4-STABLE) + 2026-04-21 15:45:32 UTC (releng/14.4, 14.4-RELEASE-p2) + 2026-04-21 15:46:03 UTC (releng/14.3, 14.3-RELEASE-p11) + 2026-04-21 15:43:57 UTC (stable/13, 13.5-STABLE) + 2026-04-21 15:47:08 UTC (releng/13.5, 13.5-RELEASE-p12) +CVE Name: CVE-2026-6386 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +Memory protection keys are an amd64 CPU feature, available in modern Intel and +AMD CPUs, which allow applications to apply access restrictions to regions of +virtual memory. On FreeBSD this functionality is provided by the pkru(3) +interface. + +II. Problem Description + +In order to apply a particular protection key to an address range, the kernel +must update the corresponding page table entries. The subroutine which handled +this failed to take into account the presence of 1GB largepage mappings created +using the shm_create_largepage(3) interface. In particular, it would always +treat a page directory page entry as pointing to another page table page. + +III. Impact + +The bug can be abused by an unprivileged user to cause pmap_pkru_update_range() +to treat userspace memory as a page table page, and thus overwrite memory to +which the application would otherwise not have access. + +IV. Workaround + +No workaround is available. The bug only affects amd64 systems. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date, +and reboot the system. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-15.patch +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-15.patch.asc +# gpg --verify amd64-15.patch.asc + +[FreeBSD 14.4 and 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-14.patch +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-14.patch.asc +# gpg --verify amd64-14.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-13.patch +# fetch https://security.FreeBSD.org/patches/SA-26:11/amd64-13.patch.asc +# gpg --verify amd64-13.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 9331e62e8b80 stable/15-n283066 +releng/15.0/ 649db49403a7 releng/15.0-n281023 +stable/14/ 4c0e5e3cc441 stable/14-n273998 +releng/14.4/ 5787df30dc3e releng/14.4-n273686 +releng/14.3/ 979e645dd25e releng/14.3-n271486 +stable/13/ b8fc56193068 stable/13-n259846 +releng/13.5/ a2f6f2d00125 releng/13.5-n259211 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-6386> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:11.amd64.asc> +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoakACgkQbljekB8A +Gu8xHBAA0UShf6OLTcPprJ4YbzORKrmUeN6MPSwrvtn792T01Fi7zXj1IeBd1/N1 +25SI2GBhoMWP1wBR9G0Er8Vjv9cn4lnuWCeBIMmaofgLUi/UahT5lLhQGG7e3ypq +DdmfyWwnJ7tAkDvxHUH2t3STjzIsQaH2NSTpxcg5bdSbGSPGr7On2RBKalvLLBon +SUx8FtlOpDj+TttxidoQcYeez8vCkdgn9PCbA/9cxZlFmy+ioE/14PQU2TAYbcnK +mZ3BWOKxRDlBN9zHBwkaSdIgjs6+t0/pCYrlUu2nCaZ9o6dtn/6WtulcuCB/l9DQ +UABsdc2uhCZvafdN316lABxaPLm3+uvcOFqRZs24tkLOYk5JxBYQQdaHrZ4cP+xS +IgQf/Zl5s/ZlwfzOjzTg54KLyH7yxR5iJ/JIJ2mRJ5PZ9wavYGM6czf4l9w+sYQw +wTTQSO/zdLRHgcKUYdq+xpv2AWEkjkZSRxRQhgMZ9rS5V+1MqhnCLs9uCsG/Ns7c +Yv7t8I+r7j3gjdEFJRDVW+awHQR2ppI/odmyABaThG3bBdPxXy9pR0IvSYtZKGEW +cUjYp2intHCDna0TSa4nzrTlCZCAZijVKeVLXSrYNvrJ9nE3dB8oESP2YASjyJBM +VxpRYXmjprazBYcRgt7kf/tSfpky7Cq59H1NU+pVxaR5TAzWvaI= +=kWUu +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:12.dhclient.asc b/website/static/security/advisories/FreeBSD-SA-26:12.dhclient.asc new file mode 100644 index 0000000000..531af13cae --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:12.dhclient.asc @@ -0,0 +1,155 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:12.dhclient Security Advisory + The FreeBSD Project + +Topic: Remote code execution via malicious DHCP options + +Category: core +Module: dhclient +Announced: 2026-04-29 +Credits: Joshua Rogers of AISLE Research Team +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:47 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:28 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:50 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:41 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:22 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:06 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:18 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-42511 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +dhclient(8) is the default IPv4 DHCP client used on FreeBSD. It is +responsible for contacting DHCP servers on a network segment and for +initialising and configuring network interfaces based on received +information. + +II. Problem Description + +The BOOTP file field is written to the lease file without escaping embedded +double-quotes, allowing injection of arbitrary dhclient.conf directives. +When the lease file is subsequently re-parsed by dhclient, e.g., after a +system restart, an attacker-controlled field from the lease is passed to +dhclient-script(8), which evaluates it. + +III. Impact + +A rogue DHCP server may be able to execute arbirary code as root on a system +running dhclient. + +IV. Workaround + +No workaround is available. Systems not running dhclient(8) are not +affected. + +The attacker needs to be on the same broadcast domain and respond to DHCP +requests. A well-managed network will configure DHCP snooping on switches to +prevent rogue DHCP servers from operating. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:12/dhclient.patch +# fetch https://security.FreeBSD.org/patches/SA-26:12/dhclient.patch.asc +# gpg --verify dhclient.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart the applicable daemons, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 2621f6c5d4ae stable/15-n283377 +releng/15.0/ e7b4fb41aafa releng/15.0-n281029 +stable/14/ b3087e05e848 stable/14-n274076 +releng/14.4/ 73b801e3b5b3 releng/14.4-n273691 +releng/14.3/ dda71167a101 releng/14.3-n271492 +stable/13/ 46c01e4dd102 stable/13-n259859 +releng/13.5/ a2d45189b9ee releng/13.5-n259215 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-42511> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:12.dhclient.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySScbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrv/HEQANr71RMaW0408Cp2xZ/n +DN8DsU7vCXPDcZWF/HAl+COurXipEycxnP6pBdm2uCqRGWXmNPkjyA5nyoAM2qYP +9b3rXQHKdrqc0vvbjJuahzqfttwcv1jFQp+8Z8N8TYWUnETprai5VOwZ+7p2caGC +gZg3UkS8qx7+qUZn1c1nOpYgW7AE1cxuBzSM3O/4pyaSnnMGgeUcz/utv+F272rn +/rdDaC1nvH09OKIJOqBxOQ7m7izTBu70P1zhuWmGDAzmvy1sNCUpv325iFBc7B78 +fRvINps878aSqheJqIx2jpeykW+nBjbVpsh++0ZUNjoWQTbZM7WaxNJxD4KjdInW +zvK24qX34aMrY4pS0BjpQ46RTkEIDFnzSYTUAN+33LQ9rQ+1DaUF0UJAlO10XBQ+ +6J1ZDXnSmqOsXu2pnRyXWKrsliz6+j3LOzkJoc2gQFwiDzex20ZJtO3Jd2dVMJ5a +F/jN5SY800LhvCbPFPL4k03xK98n7fLs432jsJOMYtRvY9N62oEbufBj0dCS0S15 +A7Vj537ziRZuGt4xz3vdE48GEBdxm+frPNadS8IurW1gDN4Rr0d5VLfKFwMsiSXr +baVMWTjn6kcfpomYDhl5451lDAyhZ20qFxx9M1lRNj7ploz4khmdv1e1zqENocQd +t4eQrptk4YUgxEIZ0R56b2qf +=h/Vp +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:13.exec.asc b/website/static/security/advisories/FreeBSD-SA-26:13.exec.asc new file mode 100644 index 0000000000..e4a6d99159 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:13.exec.asc @@ -0,0 +1,150 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:13.exec Security Advisory + The FreeBSD Project + +Topic: Local privilege escalation via execve() + +Category: core +Module: execve(2) +Announced: 2026-04-29 +Credits: Ryan of Calif.io +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:46 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:27 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:49 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:40 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:21 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:05 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:17 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-7270 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +execve(2) is a system call is used to launch an executable image, including +scripts prefixed with a path to the interpreter. The system call takes a +path to the image as a parameter, followed by extra arguments and environment +variables to be passed to the new image. + +II. Problem Description + +An operator precedence bug in the kernel results in a scenario where a buffer +overflow causes attacker-controlled data to overwrite adjacent execve(2) +argument buffers. + +III. Impact + +The bug may be exploitable by an unprivileged user to obtain superuser +privileges. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date, +and reboot the system. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:13/exec.patch +# fetch https://security.FreeBSD.org/patches/SA-26:13/exec.patch.asc +# gpg --verify exec.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ c3e943e78e06 stable/15-n283376 +releng/15.0/ 934b48683c4f releng/15.0-n281028 +stable/14/ ae00a52921ca stable/14-n274075 +releng/14.4/ 943aa64ba91a releng/14.4-n273690 +releng/14.3/ f04c40607b8f releng/14.3-n271491 +stable/13/ d619e3a3c0ec stable/13-n259858 +releng/13.5/ 7c5c37ac8f8f releng/13.5-n259214 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-7270> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:13.exec.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnyTiobFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvVDoP/2CASXfMizRLg2uhf7ab +Rq2AlXil/b3uDA316fV30LeAEc1X16VVRwuZbOPd8oovXnpt6ACj26Yg+4IsPyU9 +ZEMNcm5tA0eEqicFrrVBNxyA41QMwB1S36+tyzoZ3CTWndTAu/5yVLb0VWoniW9S +cvf8xULDWBVI48DUKuJ86Bh5aUPNMy2bCMaQc5V88aK5Cc4CG2ZWJu3pJa4+MWq2 +CBXgOA3k3qqTIQ5imrRl+9RFYe5WAEnAYNWRauXmQKeJA41bDseUB/Bghy6KY3y+ +uuIelphX3pz36cRQd83CIs6IjH0TQ0slizGsmdQ8jVDEbK+kWzSegOo90E8hepQg +p929lZbUhpg98G2Fv7cLQ1W7+39dqrqcJubXb0xUcvBp6b9uEUJigRaYJJjxFBUc +wtR6sTMqZeyQE/EDubgKMepaY7BWe8K/kDRFzPuGf3LSxZUFtXdsXHixOz6GUBjT +oRgtF/QyPIDBlxzWriBI7hbY/4vcQ/XQ7/Q4+x5Q28CNsmw9dmqrolCel8Tvaqmy +eFbbIDl+tQn+GolIs9xudzTx4lu1DGYrONoK7Gpb83UxQahkeUEryqhUJApxBskk +3Yt8nG0wWP2U8rZ8JbrWAFNIZU4/j6t+FcFctuh1bnyd88bSuQgEMbcGZ40AP9nS +LBz716wDKXX8EOoJT6jjwZ7u +=VIf8 +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:14.pf.asc b/website/static/security/advisories/FreeBSD-SA-26:14.pf.asc new file mode 100644 index 0000000000..c5d889135b --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:14.pf.asc @@ -0,0 +1,168 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:14.pf Security Advisory + The FreeBSD Project + +Topic: pf can overflow the stack parsing crafted SCTP packets + +Category: core +Module: pf +Announced: 2026-04-29 +Credits: Igor Gabriel Sousa e Souza +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:50 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:30 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:52 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:44 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:20 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:08 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:20 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-7164 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +pf is an Internet Protocol packet filter originally written for OpenBSD. +SCTP is a transport protocol with multihome support. + +pf parses SCTP packets to discover additional addresses for SCTP endpoints, +allowing it to create states allowing connections between these additional +addresses. + +II. Problem Description + +Incorrect packet validation allowed unbounded recursion parsing SCTP chunk +parameters. This can eventually result in a stack overflow and panic. + +III. Impact + +Remote attackers can craft packets which cause affected systems to panic. +This affects any system where pf is configured to process traffic, +independent of the configured ruleset. + +IV. Workaround + +No workaround is available. Systems not using pf are not affected. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date, +and reboot the system. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 15.0] +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-150.patch +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-150.patch.asc +# gpg --verify pf-150.patch.asc + +[FreeBSD 14.4] +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-144.patch +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-144.patch.asc +# gpg --verify pf-144.patch.asc + +[FreeBSD 14.3] +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-143.patch +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-143.patch.asc +# gpg --verify pf-143.patch.asc + +[FreeBSD 13.5] +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-135.patch +# fetch https://security.FreeBSD.org/patches/SA-26:14/pf-135.patch.asc +# gpg --verify pf-135.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ e1c9f92130e8 stable/15-n283379 +releng/15.0/ c01d9bcf0cf6 releng/15.0-n281031 +stable/14/ ba21845e94dd stable/14-n274078 +releng/14.4/ 0cbe512c7a80 releng/14.4-n273693 +releng/14.3/ 63495b09ccf5 releng/14.3-n271490 +stable/13/ ed0e766f1256 stable/13-n259861 +releng/13.5/ 0ab05345fb40 releng/13.5-n259217 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-7164> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:14.pf.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySS0bFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvIZAP/1GsgtB+t9rl+cOV5dv6 +EeW82SX6ivf2GdmjiuXGSKoGuw3VsXPUC4RCcnFoewr1dmh+p0mGGnN0mH7lwXlT +8HG/ZF5sRXAvbaqMt2t2kPh6RbSUTfDm9TWpFQRCUmCn2PjAtrZtjQAjEZZOhfAS +domShW7gUMTHl5AA3bpSWyL/GL2/WicOkhczJAoRg8rlUiFmTg8OYWPmSZfXfLtf +E5AeXlfn5OaXFFupB+FKsdQDShU2p01kh6BtpyfH6TXa7a2yM3Cu4OdL37oy+TSi +OgH3G7/CveNXqRknOD5DJi/kwIGbWpGLGnyAerOepY3MMq8Wag5Wz0Ive2H6B6Ud +45v7cmXhDUUaNv/vAW/q+oiru0qJKzEvOlL7RWOxDLz1eL1P8Cqj9fJBLmD9Z3GW +t4QwGS09bkDcvkxyLh4HkrHwuOmZIP/OXfdHZji98N7tgmvepiNdv8e+Ww2Pm/Oc +M+E+44nx2grOpo5kewoUUT9KPxNMwn2h91Pdh2qLFCAb/HTuJ9cpPcoKvw2DAsYz +6IGLxUjQA13kkD9J7ehlvEd1/OaYxBeRIBVIJAxV2Y3OJMLhQRCu1HKz1ACNkQY0 +/wHT5DXf4Q8PfGCEyEjtRI/tVAtVFdojSAfyWuxfusSjTxGD6SAz/MjWKI0oqGPZ +oTn0P+vVYzU3/bYgLl6DYOCP +=dRoD +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:15.dhclient.asc b/website/static/security/advisories/FreeBSD-SA-26:15.dhclient.asc new file mode 100644 index 0000000000..eea9108dc8 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:15.dhclient.asc @@ -0,0 +1,159 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:15.dhclient Security Advisory + The FreeBSD Project + +Topic: Remotely triggerable out-of-bounds heap write in dhclient + +Category: core +Module: dhclient +Announced: 2026-04-29 +Credits: Joshua Rogers of AISLE Research Team +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:49 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:29 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:51 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:42 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:24 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:07 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:19 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-42512 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +dhclient(8) is the default IPv4 DHCP client used on FreeBSD. It is +responsible for contacting DHCP servers on a network segment and for +initialising and configuring network interfaces based on received +information. + +When processing a DHCP offer, dhclient passes various parameters provided by +the server to dhclient-script(8). DHCP options, as documented in +dhcp-options(5), are passed via the environment. + +II. Problem Description + +As dhclient is building an environment to pass to dhclient-script, it may +need to resize the array of string pointers. The code which expands the +array incorrectly calculates its new size when requesting memory, resulting +in a heap buffer overrun. + +III. Impact + +A specially crafted packet can cause dhclient to overrun its buffer of +environment entries. This can result in a crash, but it may be possible to +leverage this bug to achieve remote code execution. + +IV. Workaround + +No workaround is available. Systems not running dhclient(8) are not +affected. + +The attacker needs to be on the same broadcast domain and respond to DHCP +requests. A well-managed network will configure DHCP snooping on switches to +prevent rogue DHCP servers from operating. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:15/dhclient.patch +# fetch https://security.FreeBSD.org/patches/SA-26:15/dhclient.patch.asc +# gpg --verify dhclient.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart the applicable daemons, or reboot the system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 4408b683d237 stable/15-n283378 +releng/15.0/ 66d6c32ce7b8 releng/15.0-n281030 +stable/14/ a813012f4b76 stable/14-n274077 +releng/14.4/ d60456d859a1 releng/14.4-n273692 +releng/14.3/ 76734958a098 releng/14.3-n271493 +stable/13/ 5d3e93fda7ce stable/13-n259860 +releng/13.5/ 5a5e7883a3bb releng/13.5-n259216 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-42512> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:15.dhclient.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTMbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvvwIP/3DfD428ehRM/ukPC7bY +2AUpIfE5s+AHvE6JiRF8IcbsuVRHsMfO1Z6YWYMfPxhzTpoKhjBcC1XuM6fMugcP +9GFRoW1u4f17trfSSTFMbgTA6q7EC1hab1wQsGhpgazQA+lGpUjoISC88ah+jiEu ++Z1b9ubyuYURnstf5V5gj3cRunt9YL3ZuBC0oJJaybODJSuVvuvgZL3QvtwSGM98 +OJmqEANEYO3uGpkbeJsIXBYvzqJdzVHpp/rVF84+PHYLp/uqVaWFllflWLwEp6wE +0oSKmsWljjPjL2bIcbsxu+aJH4XJDwDizgYRq6IVnbV/G3XYqQPJwMyQh/qGDhIq +8hA3tG/aQrs5ukL4WE7eMMM+fNzy+LTBfD3vWyfuabFHmKXBCI+Kc6q+oNcPGXeq +/ofaJav+ivO4d0H6XHIJ/MtZOO9782EXYWmR8X8E4myZ4z6/vtmqUzL457Kh2v7b +rdGE/1tdd+CyIVobfcuPJBq0cx8Fp8gVydcQ7Ts6i5Hqx/Grz2za5qvQgsHsruqo +ZQxb3rw7J6wp7w7duqEl9cYVZRgz9CdmTSmjCPi8Ws3nO0PCBV220/dHBHi/kPtl +f2GPmIBJA2s0HjTiPQJp9LAFaAnUuCsleo4PEj04NDe6QFMt/u1W22AZbO50zCOQ +wuVe9dL9HWnNoKuR1hjIWB27 +=rnNn +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:16.libnv.asc b/website/static/security/advisories/FreeBSD-SA-26:16.libnv.asc new file mode 100644 index 0000000000..7cf5e02322 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:16.libnv.asc @@ -0,0 +1,152 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:16.libnv Security Advisory + The FreeBSD Project + +Topic: Stack overflow via select() file descriptor set overflow + +Category: core +Module: libnv +Announced: 2026-04-29 +Credits: Joshua Rogers of AISLE Research Team +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:51 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:32 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:56 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:47 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:27 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:09 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:21 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-39457 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +libnv is a general-purpose library designed for storing and exchanging sets +of name-value pairs. This library can serve as an Inter-Process +Communication (IPC) framework, enabling processes to exchange data and file +descriptors. For example, it is used in libcasper to establish communication +between privileged and unprivileged processes. Additionally, libnv can +function as an interface for communication between userland and kernel. + +Originally, libnv was inspired by OpenZFS' nvlist implementation. However, +the implementations are separate. This advisory relates only to the base +system implementation of libnv, not to the one in OpenZFS. + +II. Problem Description + +When exchanging data over a socket, libnv uses select(2) to wait for data to +arrive. However, it does not verify whether the provided socket descriptor +fits in select(2)'s file descriptor set size limit of FD_SETSIZE (1024). + +III. Impact + +An attacker who is able to force a libnv application to allocate large file +descriptors, e.g., by opening many descriptors and executing a program which +is not careful to close them upon startup, can trigger stack corruption. If +the target application is setuid-root, then this could be used to elevate +local privileges. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date +and reboot. + +Perform one of the following: + +1) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) +utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:16/libnv.patch +# fetch https://security.FreeBSD.org/patches/SA-26:16/libnv.patch.asc +# gpg --verify libnv.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +d) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 025789eaa648 stable/15-n283380 +releng/15.0/ 7e4d5363ddce releng/15.0-n281032 +stable/14/ 45809b0e1bc1 stable/14-n274081 +releng/14.4/ a5cb4863d65a releng/14.4-n273696 +releng/14.3/ a872c32f389e releng/14.3-n271496 +stable/13/ 4acc2b5c61a7 stable/13-n259862 +releng/13.5/ 32d12677ff45 releng/13.5-n259218 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-39457> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:16.libnv.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTUbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvEdwQAKF0kwMDT0ZjvcDnvqXa +NmJEse7XRdFDWDcMp8NtSQK5DTYBRpUgwWiC7M+HRr4QIf/aIjzwuJdu1luK913i +vAJJUbAaEAdGbNqd35FtDlnTWQE638R4HQ0TqMBrUfGTSp0O5SPOpTSPXB1Fw/F7 +Q3c22lNDHgxgZ8+DOoJH70HgjdVskz3ezZroYUKfmk5vh9yZtVM9zMr6iGr6TUA7 +OEbIrMlRCJ3pI9dOSGNKz1i/3s8bMS3U3nvAWIYPdSjKQBOyRdHoZHtk4SfY9TVs +epqQQccUv9g5+E1QgxxoQHLR4dLkCHEJKOU2sqc/qW9KISX2rsTd2UYgYubxtb+j +CIzTg23/rkMMhCi3VZ9NVLmGrxZclxyvAVJ/V3942jjag0c1onc+5RH0IGAljgay +hobn3CBqE2NIOjoFyCJK9RcZ+wtvxFoQFdX6A56h5vDD2I/H7MIFJ0EnW3aWvT8f +0xiWhD4//9AU3+06soPt6l4tE/YaXJbcvYb92kC1JbbGVApMrDYbdxu3QK8HwAlV +mNTFd3hgoEzlCiFH9vDNK/RIsVE67kb4KjqZKC1ElWrQbawQZtnKUigpxGcZbhCC +9zwXgoFRHCzeBiO77anQMgArNuY3Wj29beepzCvOA7u/KRyDTvDat8YRWNKbWS5L +T3cMyFqgRkUgr7tajk0L51Xx +=Edvm +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisories/FreeBSD-SA-26:17.libnv.asc b/website/static/security/advisories/FreeBSD-SA-26:17.libnv.asc new file mode 100644 index 0000000000..7c9a1f5833 --- /dev/null +++ b/website/static/security/advisories/FreeBSD-SA-26:17.libnv.asc @@ -0,0 +1,156 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-26:17.libnv Security Advisory + The FreeBSD Project + +Topic: Heap overflow in libnv + +Category: core +Module: libnv +Announced: 2026-04-29 +Credits: Mariusz Zaborski +Affects: All supported versions of FreeBSD. +Corrected: 2026-04-29 14:47:52 UTC (stable/15, 15.0-STABLE) + 2026-04-29 14:48:33 UTC (releng/15.0, 15.0-RELEASE-p7) + 2026-04-29 14:48:57 UTC (stable/14, 14.4-STABLE) + 2026-04-29 14:49:48 UTC (releng/14.4, 14.4-RELEASE-p3) + 2026-04-29 14:49:28 UTC (releng/14.3, 14.3-RELEASE-p12) + 2026-04-29 14:50:10 UTC (stable/13, 13.5-STABLE) + 2026-04-29 14:50:22 UTC (releng/13.5, 13.5-RELEASE-p13) +CVE Name: CVE-2026-35547 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit <URL:https://security.FreeBSD.org/>. + +I. Background + +libnv is a general-purpose library designed for storing and exchanging sets +of name-value pairs. This library can serve as an Inter-Process +Communication (IPC) framework, enabling processes to exchange data and file +descriptors. For example, it is used in libcasper to establish communication +between privileged and unprivileged processes. Additionally, libnv can +function as an interface for communication between userland and kernel. + +Originally, libnv was inspired by OpenZFS' nvlist implementation. However, +the implementations are separate. This advisory relates only to the base +system implementation of libnv, not the one in OpenZFS. + +II. Problem Description + +When processing the header of an incoming message, libnv failed to properly +validate the message size. + +III. Impact + +The lack of validation allows a malicious program to write outside the bounds +of a heap allocation. This can trigger a crash or system panic, and it may +be possible for an unprivileged user to exploit the bug to elevate their +privileges. + +IV. Workaround + +No workaround is available. + +V. Solution + +Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +Perform one of the following: + +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" + +2) To update your vulnerable system installed from binary distribution sets: + +Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +10min "Rebooting for a security update" + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/SA-26:17/libnv.patch +# fetch https://security.FreeBSD.org/patches/SA-26:17/libnv.patch.asc +# gpg --verify libnv.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +This issue is corrected as of the corresponding Git commit hash in the +following stable and release branches: + +Branch/path Hash Revision +- ------------------------------------------------------------------------- +stable/15/ 414e25d7d512 stable/15-n283381 +releng/15.0/ b345e07c8d71 releng/15.0-n281033 +stable/14/ 1cbd6e148249 stable/14-n274082 +releng/14.4/ 4f0992ce23b0 releng/14.4-n273697 +releng/14.3/ aa15809f85de releng/14.3-n271497 +stable/13/ 05b91c2a7106 stable/13-n259863 +releng/13.5/ f7f48005fbe2 releng/13.5-n259219 +- ------------------------------------------------------------------------- + +Run the following command to see which files were modified by a +particular commit: + +# git show --stat <commit hash> + +Or visit the following URL, replacing NNNNNN with the hash: + +<URL:https://cgit.freebsd.org/src/commit/?id=NNNNNN> + +To determine the commit count in a working tree (for comparison against +nNNNNNN in the table above), run: + +# git rev-list --count --first-parent HEAD + +VII. References + +<URL:https://www.cve.org/CVERecord?id=CVE-2026-35547> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-26:17.libnv.asc> +-----BEGIN PGP SIGNATURE----- + +iQJPBAEBCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTgbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvV+cQANyoTjQKCgT/ObIaHIvn +/ZHiHhWtxqpnOGHiJQ/Pu32XfF4zngUmxH3RFM4V+p2QTKd+OnCojcr/nWjS1Xh4 +D2G0TUYeTfEUzERLxODtWSxD6Px0n7qutRgpTx9yLid3N34av93aoQYnK+1FkqAf +PonQlVKqI2Ab44879/Aw4glrjNQg2kGzAwSA4Nzik96BZMePQk6sDnzNKODz914O +khZ6KDSc9Fc0jUS4RZUh1AXnAEV2a7vD3fQLg+8aegFiaIajnC4dFZPjl1jioawp +0Jm0f1UI/n5jfp/zyHCJZIgDNvcX+laFnLRJuB8XCrWk8luFdpVOTUjsuPMSA737 +TwdSG05ZnGhWsJhQjK0mdkDxoH81wWW7mz21jjVBJ9UhaWhGMNV4mBSevfFYkFkb +JHuHO0aCUB6e6/MJ/7O6d0tG9etdQUjCpQeLqXKiYQKqjQkplUUL0C2Uy7A4otEu +MelMjHsQMQEjUpRVxX4IADyNQgtJjrroFDdoez3oBF1dfBxQrKkWBnKTTYrV6cbl +fIVmkl2b6B/0FcGhAekDh1tLvHj4Ul0n8wzb19F7vT1+4QlnLOtIrXZcJdsTbqde +tKRoUYcwvBpUn2bsefxWzEPZ9jvSBoIkSwPmSnu8zQ1jY44eyiHodaXkMsZygplL +WfRkGmyutQ0XdUuhcCSyfi/G +=K9xn +-----END PGP SIGNATURE----- diff --git a/website/static/security/advisory-template.txt b/website/static/security/advisory-template.txt index 62babddd4d..132d270140 100644 --- a/website/static/security/advisory-template.txt +++ b/website/static/security/advisory-template.txt @@ -1,22 +1,23 @@ ============================================================================= -FreeBSD-SA-ADVISORY_TEMPLATE Security Advisory +FreeBSD-SA-XX_ADVISORY_TEMPLATE Security Advisory The FreeBSD Project -Topic: +Topic: XX -Category: < core | contrib > -Module: <module name> -Announced: 2025-XX-XX -Credits: -Affects: <affected versions> +Category: <XX core | contrib > +Module: <XX module name> +Announced: 2026-XX-XX +Credits: XX +Affects: <XX affected versions> <e.g., "All supported versions of FreeBSD.", "FreeBSD - 13.5 and later.", "FreeBSD 13.x", or "FreeBSD 14.3"> -Corrected: 2025-XX-XX XX:XX:XX UTC (stable/15, 15.0-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/15.0, 15.0-RELEASE-pXX) - 2025-XX-XX XX:XX:XX UTC (stable/14, 14.3-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/14.3, 14.3-RELEASE-pXX) - 2025-XX-XX XX:XX:XX UTC (stable/13, 13.5-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/13.5, 13.5-RELEASE-pXX) + 13.5 and later.", "FreeBSD 13.x", or "FreeBSD 14.4"> +Corrected: 2026-XX-XX XX:XX:XX UTC (stable/15, 15.0-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/15.0, 15.0-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (stable/14, 14.4-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/14.4, 14.4-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (releng/14.3, 14.3-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (stable/13, 13.5-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/13.5, 13.5-RELEASE-pXX) CVE Name: CVE-XXXX-XXXX For general information regarding FreeBSD Security Advisories, @@ -25,31 +26,31 @@ following sections, please visit <URL:https://security.FreeBSD.org/>. I. Background -<brief description of what the affected bits are supposed to do> +<XX brief description of what the affected bits are supposed to do> II. Problem Description -<detailed description of the problem> +<XX detailed description of the problem> III. Impact -<description as to why the above problem is bad> +<XX description as to why the above problem is bad> IV. Workaround -<If no workaround exists:> +<XX If no workaround exists:> No workaround is available. -<... but some systems are unaffected:> +<XX ... but some systems are unaffected:> No workaround is available. <insert simple description of some systems that are not vulnerable> -<If a workaround exists:> -<insert workaround here> +<XX If a workaround exists:> +<XX insert workaround here> V. Solution -<insert solution here> +<XX insert solution here> Upgrade your vulnerable system to a supported FreeBSD stable or release / security branch (releng) dated after the correction date. @@ -57,17 +58,26 @@ release / security branch (releng) dated after the correction date. Perform one of the following: -1) To update your vulnerable system via a binary patch: +1) To update your vulnerable system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +# shutdown -r +10min "Rebooting for a security update" <XX if required> + +2) To update your vulnerable system installed from binary distribution sets: Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, -or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) -utility: +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: # freebsd-update fetch # freebsd-update install # shutdown -r +10min "Rebooting for a security update" <XX if required> -2) To update your vulnerable system via a source code patch: +3) To update your vulnerable system via a source code patch: The following patches have been verified to apply to the applicable FreeBSD release branches. @@ -75,7 +85,7 @@ FreeBSD release branches. a) Download the relevant patch from the location below, and verify the detached PGP signature using your PGP utility. -[FreeBSD 13.3] +[FreeBSD XX] # fetch https://security.FreeBSD.org/patches/SA-XX:XX/XXXX.patch # fetch https://security.FreeBSD.org/patches/SA-XX:XX/XXXX.patch.asc # gpg --verify XXXX.patch.asc @@ -85,26 +95,26 @@ b) Apply the patch. Execute the following commands as root: # cd /usr/src # patch < /path/to/patch -<for a userland utility:> +<XX for a userland utility:> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. -<for a daemons> +<XX for a daemons> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. Restart the applicable daemons, or reboot the system. -<for a common library> +<XX for a common library> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. Restart all daemons that use the library, or reboot the system. -<for a kernel vulnerability:> +<XX for a kernel vulnerability:> c) Recompile your kernel as described in <URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the @@ -120,6 +130,7 @@ Branch/path Hash Revision stable/15/ XXXXXXXXXXXX stable/15-nXXXXXX releng/15.0/ XXXXXXXXXXXX releng/15.0-nXXXXXX stable/14/ XXXXXXXXXXXX stable/14-nXXXXXX +releng/14.4/ XXXXXXXXXXXX releng/14.4-nXXXXXX releng/14.3/ XXXXXXXXXXXX releng/14.3-nXXXXXX stable/13/ XXXXXXXXXXXX stable/13-nXXXXXX releng/13.5/ XXXXXXXXXXXX releng/13.5-nXXXXXX @@ -141,9 +152,9 @@ nNNNNNN in the table above), run: VII. References -<other info on vulnerability> +<XX other info on vulnerability> -<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-XXXX-XXXX> +<URL:https://www.cve.org/CVERecord?id=CVE-XXXX-XXXXX> The latest revision of this advisory is available at <URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-XX:XX.XXXXX.asc> diff --git a/website/static/security/errata-template.txt b/website/static/security/errata-template.txt index 48b11f6823..e6e489ba1e 100644 --- a/website/static/security/errata-template.txt +++ b/website/static/security/errata-template.txt @@ -1,22 +1,23 @@ ============================================================================= -FreeBSD-EN-ERRATA_TEMPLATE Errata Notice +FreeBSD-EN-XX_ERRATA_TEMPLATE Errata Notice The FreeBSD Project -Topic: +Topic: XX -Category: < core | contrib > -Module: <module name> -Announced: 2025-XX-XX -Credits: -Affects: <affected versions> +Category: <XX core | contrib > +Module: <XX module name> +Announced: 2026-XX-XX +Credits: XX +Affects: <XX affected versions> <e.g., "All supported versions of FreeBSD.", "FreeBSD - 13.5 and later.", "FreeBSD 13.x", or "FreeBSD 14.3"> -Corrected: 2025-XX-XX XX:XX:XX UTC (stable/15, 15.0-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/15.0, 15.0-RELEASE-pXX) - 2025-XX-XX XX:XX:XX UTC (stable/14, 14.3-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/14.3, 14.3-RELEASE-pXX) - 2025-XX-XX XX:XX:XX UTC (stable/13, 13.5-STABLE) - 2025-XX-XX XX:XX:XX UTC (releng/13.5, 13.5-RELEASE-pXX) + 13.5 and later.", "FreeBSD 13.x", or "FreeBSD 14.4"> +Corrected: 2026-XX-XX XX:XX:XX UTC (stable/15, 15.0-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/15.0, 15.0-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (stable/14, 14.4-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/14.4, 14.4-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (releng/14.3, 14.3-RELEASE-pXX) + 2026-XX-XX XX:XX:XX UTC (stable/13, 13.5-STABLE) + 2026-XX-XX XX:XX:XX UTC (releng/13.5, 13.5-RELEASE-pXX) For general information regarding FreeBSD Errata Notices and Security Advisories, including descriptions of the fields above, security @@ -25,31 +26,31 @@ branches, and the following sections, please visit I. Background -<brief description of what the affected bits are supposed to do> +<XX brief description of what the affected bits are supposed to do> II. Problem Description -<detailed description of the problem> +<XX detailed description of the problem> III. Impact -<description as to why the above problem is bad> +<XX description as to why the above problem is bad> IV. Workaround -<If no workaround exists:> +<XX If no workaround exists:> No workaround is available. -<... but some systems are unaffected:> +<XX ... but some systems are unaffected:> No workaround is available. <insert simple description of some systems that are not vulnerable> -<If a workaround exists:> -<insert workaround here> +<XX If a workaround exists:> +<XX insert workaround here> V. Solution -<insert solution here> +<XX insert solution here> Upgrade your system to a supported FreeBSD stable or release / security branch (releng) dated after the correction date. @@ -57,17 +58,26 @@ branch (releng) dated after the correction date. Perform one of the following: -1) To update your system via a binary patch: +1) To update your system installed from base system packages: + +Systems running a 15.0-RELEASE version of FreeBSD on the amd64 or arm64 +platforms, which were installed using base system packages, can be updated +via the pkg(8) utility: + +# pkg upgrade -r FreeBSD-base +[XX Needs reboot? Mention please] + +2) To update your system installed from binary distribution sets: Systems running a RELEASE version of FreeBSD on the amd64 or arm64 platforms, -or the i386 platform on FreeBSD 13, can be updated via the freebsd-update(8) -utility: +or the i386 platform on FreeBSD 13, which were not installed using base +system packages, can be updated via the freebsd-update(8) utility: # freebsd-update fetch # freebsd-update install [XX Needs reboot? Mention please] -2) To update your system via a source code patch: +3) To update your system via a source code patch: The following patches have been verified to apply to the applicable FreeBSD release branches. @@ -75,7 +85,7 @@ FreeBSD release branches. a) Download the relevant patch from the location below, and verify the detached PGP signature using your PGP utility. -[FreeBSD 13.3] +[FreeBSD XX] # fetch https://security.FreeBSD.org/patches/EN-XX:XX/XXXX.patch # fetch https://security.FreeBSD.org/patches/EN-XX:XX/XXXX.patch.asc # gpg --verify XXXX.patch.asc @@ -85,26 +95,26 @@ b) Apply the patch. Execute the following commands as root: # cd /usr/src # patch < /path/to/patch -<for a userland utility:> +<XX for a userland utility:> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. -<for a daemons> +<XX for a daemons> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. Restart the applicable daemons, or reboot the system. -<for a common library> +<XX for a common library> c) Recompile the operating system using buildworld and installworld as described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. Restart all daemons that use the library, or reboot the system. -<for a kernel bug:> +<XX for a kernel bug:> c) Recompile your kernel as described in <URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the @@ -120,6 +130,7 @@ Branch/path Hash Revision stable/15/ XXXXXXXXXXXX stable/15-nXXXXXX releng/15.0/ XXXXXXXXXXXX releng/15.0-nXXXXXX stable/14/ XXXXXXXXXXXX stable/14-nXXXXXX +releng/14.4/ XXXXXXXXXXXX releng/14.4-nXXXXXX releng/14.3/ XXXXXXXXXXXX releng/14.3-nXXXXXX stable/13/ XXXXXXXXXXXX stable/13-nXXXXXX releng/13.5/ XXXXXXXXXXXX releng/13.5-nXXXXXX @@ -141,7 +152,7 @@ nNNNNNN in the table above), run: VII. References -<other info on the problem> +<XX other info on the problem> <URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=XXXXXX> diff --git a/website/static/security/patches/EN-26:01/devinfo.patch b/website/static/security/patches/EN-26:01/devinfo.patch new file mode 100644 index 0000000000..282c8124de --- /dev/null +++ b/website/static/security/patches/EN-26:01/devinfo.patch @@ -0,0 +1,477 @@ +--- usr.sbin/devinfo/Makefile.orig ++++ usr.sbin/devinfo/Makefile +@@ -2,6 +2,6 @@ + PROG= devinfo + MAN= devinfo.8 + +-LIBADD= xo devinfo ++LIBADD= devinfo + + .include <bsd.prog.mk> +--- usr.sbin/devinfo/devinfo.8.orig ++++ usr.sbin/devinfo/devinfo.8 +@@ -34,13 +34,10 @@ + .Nd print information about system device configuration + .Sh SYNOPSIS + .Nm +-.Op Fl -libxo + .Op Fl rv + .Nm +-.Op Fl -libxo + .Fl p Ar dev Op Fl v + .Nm +-.Op Fl -libxo + .Fl u Op Fl v + .Sh DESCRIPTION + The +@@ -51,14 +48,7 @@ + device. + .Pp + The following options are accepted: +-.Bl -tag -width "--libxo" +-.It Fl -libxo +-Generate output via +-.Xr libxo 3 +-in a selection of different human and machine readable formats. +-See +-.Xr xo_options 7 +-for details on command line arguments. ++.Bl -tag -width indent + .It Fl p Ar dev + Display the path of + .Ar dev +@@ -83,8 +73,6 @@ + .Sh SEE ALSO + .Xr systat 1 , + .Xr devinfo 3 , +-.Xr libxo 3 , +-.Xr xo_options 7 , + .Xr devctl 8 , + .Xr iostat 8 , + .Xr pciconf 8 , +--- usr.sbin/devinfo/devinfo.c.orig ++++ usr.sbin/devinfo/devinfo.c +@@ -4,7 +4,6 @@ + * Copyright (c) 2000, 2001 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. +- * Copyright (c) 2024 KT Ullavik + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -41,18 +40,12 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> +- +-#include <libxo/xo.h> + #include "devinfo.h" + + static bool rflag; + static bool vflag; +-static int open_tag_count; +-static char *last_res; + + static void print_indent(int); +-static void print_kvlist(char *); +-static char* xml_safe_string(char *); + static void print_resource(struct devinfo_res *); + static int print_device_matching_resource(struct devinfo_res *, void *); + static int print_device_rman_resources(struct devinfo_rman *, void *); +@@ -81,46 +74,7 @@ + n = MIN((size_t)n, sizeof(buffer) - 1); + memset(buffer, ' ', n); + buffer[n] = '\0'; +- xo_emit("{Pa:%s}", buffer); +-} +- +-/* +- * Takes a list of key-value pairs in the form +- * "key1=val1 key2=val2 ..." and prints them according +- * to xo formatting. +- */ +-static void +-print_kvlist(char *s) +-{ +- char *kv; +- char *copy; +- +- if ((copy = strdup(s)) == NULL) +- xo_err(1, "No memory!"); +- +- while ((kv = strsep(©, " ")) != NULL) { +- char* k = strsep(&kv, "="); +- xo_emit("{ea:%s/%s} {d:key/%s}={d:value/%s}", k, kv, k, kv); +- } +- free(copy); +-} +- +-static char +-*xml_safe_string(char *desc) +-{ +- int i; +- char *s; +- +- if ((s = strdup(desc)) == NULL) { +- xo_err(1, "No memory!"); +- } +- +- for (i=0; s[i] != '\0'; i++) { +- if (s[i] == ' ' || s[i] == '/') { +- s[i] = '-'; +- } +- } +- return s; ++ printf("%s", buffer); + } + + /* +@@ -132,28 +86,20 @@ + struct devinfo_rman *rman; + bool hexmode; + rman_res_t end; +- char *safe_desc; + + rman = devinfo_handle_to_rman(res->dr_rman); + hexmode = (rman->dm_size > 1000) || (rman->dm_size == 0); + end = res->dr_start + res->dr_size - 1; + +- safe_desc = xml_safe_string(rman->dm_desc); +- xo_open_instance(safe_desc); +- + if (hexmode) { +- xo_emit("{:start/0x%jx}", res->dr_start); ++ printf("0x%jx", res->dr_start); + if (res->dr_size > 1) +- xo_emit("{D:-}{d:end/0x%jx}", end); +- xo_emit("{e:end/0x%jx}", end); ++ printf("-0x%jx", end); + } else { +- xo_emit("{:start/%ju}", res->dr_start); ++ printf("%ju", res->dr_start); + if (res->dr_size > 1) +- xo_emit("{D:-}{d:end/%ju}", end); +- xo_emit("{e:end/%ju}", end); ++ printf("-%ju", end); + } +- xo_close_instance(safe_desc); +- free(safe_desc); + } + + /* +@@ -175,7 +121,7 @@ + return(1); + print_indent(ia->indent); + print_resource(res); +- xo_emit("\n"); ++ printf("\n"); + } + return(0); + } +@@ -188,7 +134,6 @@ + { + struct indent_arg *ia = (struct indent_arg *)arg; + int indent; +- char *safe_desc; + + indent = ia->indent; + +@@ -198,18 +143,13 @@ + print_device_matching_resource, ia) != 0) { + + /* there are, print header */ +- safe_desc = xml_safe_string(rman->dm_desc); + print_indent(indent); +- xo_emit("<{:description/%s}>\n", rman->dm_desc); +- xo_open_list(safe_desc); ++ printf("%s:\n", rman->dm_desc); + + /* print resources */ + ia->indent = indent + 4; + devinfo_foreach_rman_resource(rman, + print_device_matching_resource, ia); +- +- xo_close_list(safe_desc); +- free(safe_desc); + } + ia->indent = indent; + return(0); +@@ -220,39 +160,20 @@ + { + if (vflag) { + if (*dev->dd_desc) { +- xo_emit("<{:description/%s}>", dev->dd_desc); ++ printf(" <%s>", dev->dd_desc); + } + if (*dev->dd_pnpinfo) { +- xo_open_container("pnpinfo"); +- xo_emit("{D: pnpinfo}"); +- +- if ((strcmp(dev->dd_pnpinfo, "unknown") == 0)) +- xo_emit("{D: unknown}"); +- else +- print_kvlist(dev->dd_pnpinfo); +- +- xo_close_container("pnpinfo"); ++ printf(" pnpinfo %s", dev->dd_pnpinfo); + } + if (*dev->dd_location) { +- xo_open_container("location"); +- xo_emit("{D: at}"); +- print_kvlist(dev->dd_location); +- xo_close_container("location"); ++ printf(" at %s", dev->dd_location); + } +- +- // If verbose, then always print state for json/xml. +- if (!(dev->dd_flags & DF_ENABLED)) +- xo_emit("{e:state/disabled}"); +- else if (dev->dd_flags & DF_SUSPENDED) +- xo_emit("{e:state/suspended}"); +- else +- xo_emit("{e:state/enabled}"); + } + + if (!(dev->dd_flags & DF_ENABLED)) +- xo_emit("{D: (disabled)}"); ++ printf(" (disabled)"); + else if (dev->dd_flags & DF_SUSPENDED) +- xo_emit("{D: (suspended)}"); ++ printf(" (suspended)"); + } + + /* +@@ -262,20 +183,16 @@ + print_device(struct devinfo_dev *dev, void *arg) + { + struct indent_arg ia; +- int indent, ret; +- const char* devname = dev->dd_name[0] ? dev->dd_name : "unknown"; ++ int indent; + bool printit = vflag || (dev->dd_name[0] != 0 && + dev->dd_state >= DS_ATTACHED); + + if (printit) { + indent = (int)(intptr_t)arg; + print_indent(indent); +- +- xo_open_container(devname); +- xo_emit("{d:devicename/%s}", devname); +- ++ printf("%s", dev->dd_name[0] ? dev->dd_name : "unknown"); + print_device_props(dev); +- xo_emit("\n"); ++ printf("\n"); + if (rflag) { + ia.indent = indent + 4; + ia.arg = dev; +@@ -284,13 +201,8 @@ + } + } + +- ret = (devinfo_foreach_device_child(dev, print_device, ++ return(devinfo_foreach_device_child(dev, print_device, + (void *)((char *)arg + 2))); +- +- if (printit) { +- xo_close_container(devname); +- } +- return(ret); + } + + /* +@@ -302,7 +214,6 @@ + struct devinfo_dev *dev; + struct devinfo_rman *rman; + rman_res_t end; +- char *res_str, *entry = NULL; + bool hexmode; + + dev = devinfo_handle_to_device(res->dr_device); +@@ -310,38 +221,24 @@ + hexmode = (rman->dm_size > 1000) || (rman->dm_size == 0); + end = res->dr_start + res->dr_size - 1; + ++ printf(" "); ++ + if (hexmode) { + if (res->dr_size > 1) +- asprintf(&res_str, "0x%jx-0x%jx", res->dr_start, end); ++ printf("0x%jx-0x%jx", res->dr_start, end); + else +- asprintf(&res_str, "0x%jx", res->dr_start); ++ printf("0x%jx", res->dr_start); + } else { + if (res->dr_size > 1) +- asprintf(&res_str, "%ju-%ju", res->dr_start, end); ++ printf("%ju-%ju", res->dr_start, end); + else +- asprintf(&res_str, "%ju", res->dr_start); +- } +- +- xo_emit("{P: }"); +- +- if (last_res == NULL) { +- // First resource +- xo_open_list(res_str); +- } else if (strcmp(res_str, last_res) != 0) { +- // We can't repeat json keys. So we keep an +- // open list from the last iteration and only +- // create a new list when see a new resource. +- xo_close_list(last_res); +- xo_open_list(res_str); ++ printf("%ju", res->dr_start); + } + + dev = devinfo_handle_to_device(res->dr_device); + if (dev != NULL) { + if (dev->dd_name[0] != 0) { + printf(" (%s)", dev->dd_name); +- asprintf(&entry, "{el:%s}{D:%s} {D:(%s)}\n", +- res_str, res_str, dev->dd_name); +- xo_emit(entry, dev->dd_name); + } else { + printf(" (unknown)"); + if (vflag && *dev->dd_pnpinfo) +@@ -350,11 +247,9 @@ + printf(" at %s", dev->dd_location); + } + } else { +- asprintf(&entry, "{el:%s}{D:%s} {D:----}\n", res_str, res_str); +- xo_emit(entry, "----"); ++ printf(" ----"); + } +- free(entry); +- last_res = res_str; ++ printf("\n"); + return(0); + } + +@@ -364,16 +259,8 @@ + int + print_rman(struct devinfo_rman *rman, void *arg __unused) + { +- char* safe_desc = xml_safe_string(rman->dm_desc); +- +- xo_emit("<{:description/%s}\n>", rman->dm_desc); +- xo_open_container(safe_desc); +- ++ printf("%s:\n", rman->dm_desc); + devinfo_foreach_rman_resource(rman, print_rman_resource, 0); +- +- xo_close_list(last_res); +- xo_close_container(safe_desc); +- free(safe_desc); + return(0); + } + +@@ -382,17 +269,12 @@ + { + const char *devname = dev->dd_name[0] ? dev->dd_name : "unknown"; + +- xo_open_container(devname); +- open_tag_count++; +- xo_emit("{:devicename/%s} ", devname); ++ printf("%s", devname); + print_device_props(dev); + if (vflag) +- xo_emit("\n"); ++ printf("\n"); + } + +-/* +- * Recurse until we find the right dev. On the way up we print path. +- */ + static int + print_device_path(struct devinfo_dev *dev, void *xname) + { +@@ -406,7 +288,7 @@ + + rv = devinfo_foreach_device_child(dev, print_device_path, xname); + if (rv == 1) { +- xo_emit("{P: }"); ++ printf(" "); + print_device_path_entry(dev); + } + return (rv); +@@ -415,26 +297,19 @@ + static void + print_path(struct devinfo_dev *root, char *path) + { +- open_tag_count = 0; +- if (devinfo_foreach_device_child(root, print_device_path, +- (void *)path) == 0) +- xo_errx(1, "%s: Not found", path); ++ if (devinfo_foreach_device_child(root, print_device_path, (void *)path) == 0) ++ errx(1, "%s: Not found", path); + if (!vflag) +- xo_emit("\n"); +- +- while (open_tag_count > 0) { +- xo_close_container_d(); +- open_tag_count--; +- } ++ printf("\n"); + } + + static void __dead2 + usage(void) + { +- xo_error( +- "usage: devinfo [-rv]\n", +- " devinfo -u [-v]\n", +- " devinfo -p dev [-v]\n"); ++ fprintf(stderr, "%s\n%s\n%s\n", ++ "usage: devinfo [-rv]", ++ " devinfo -u [-v]", ++ " devinfo -p dev [-v]"); + exit(1); + } + +@@ -446,11 +321,6 @@ + bool uflag; + char *path = NULL; + +- argc = xo_parse_args(argc, argv); +- if (argc < 0) { +- exit(1); +- } +- + uflag = false; + while ((c = getopt(argc, argv, "p:ruv")) != -1) { + switch(c) { +@@ -476,32 +346,20 @@ + + if ((rv = devinfo_init()) != 0) { + errno = rv; +- xo_err(1, "devinfo_init"); ++ err(1, "devinfo_init"); + } + + if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL) +- xo_errx(1, "can't find root device"); ++ errx(1, "can't find root device"); + + if (path) { +- xo_set_flags(NULL, XOF_DTRT); +- xo_open_container("device-path"); + print_path(root, path); +- xo_close_container("device-path"); + } else if (uflag) { + /* print resource usage? */ +- xo_set_flags(NULL, XOF_DTRT); +- xo_open_container("device-resources"); + devinfo_foreach_rman(print_rman, NULL); +- xo_close_container("device-resources"); + } else { + /* print device hierarchy */ +- xo_open_container("device-information"); + devinfo_foreach_device_child(root, print_device, (void *)0); +- xo_close_container("device-information"); +- } +- +- if (xo_finish() < 0) { +- exit(1); + } + return(0); + } diff --git a/website/static/security/patches/EN-26:01/devinfo.patch.asc b/website/static/security/patches/EN-26:01/devinfo.patch.asc new file mode 100644 index 0000000000..a9497138a4 --- /dev/null +++ b/website/static/security/patches/EN-26:01/devinfo.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NCoACgkQbljekB8A +Gu9+LQ//bOMvcSgqCImoF30CMJjMBqs30TbfTMcuF8gfB4g4YilvtmzbPXnYgNm9 +RDt2faB+Mo3avyIZqFjgzvQYBS0OB9tQkPRxoafRBttp6gsnAE8q7iUJ2RY6S9qp +qql78FzsxlQpBcsONMAjmFeo6UarBBi4pcDQXFAWQO4CrXsgtjhXxdZ+e4xw2fCP +N1BfJ2hqz3kg3nztihxRHbskOK0pjaxf4eqpTDOozQvPEfG74BrUhX5meItmzVSC +FlUHI6c3fazhsUwbEMWdwp1/GOEM8Lxie7BcZG8VksRmPnojJfNKs36939yDrgX7 +GExUNMyT0aoqs4BdiFo3ruFI4o42EplnAB8wk8XhOSJUGRR8rZweN/Eh1ZstN+sf +gBDfYv03t2Apr+Ys3FHrTHIQpR6K4nFnXA2Dw1fcxy+nNx2jNKgTeB91ppMNlmce +POLoI56dLK4K6KZ71Uxj8Ty3E38AJI7n62rw6w4LjoemZim7dlrSGck1W83CqZ+0 +SiF/aghVzszU7IcZL48NNyPQQSxIrj8/TQkX5pKULlKC2gbvwY1YnRmJ+izkjvt/ +QREKhR627zgWs33ncQTjmTeO+Grz8ww1uY1dok5O/VHIwR+9zmtW0hEJ3gHryqH0 +wbUVE5nvyOaFArovizTDm0dO8vqZLbDBdYP54yuiwTIvv6yrgFc= +=XYvu +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:02/arm64-14.patch b/website/static/security/patches/EN-26:02/arm64-14.patch new file mode 100644 index 0000000000..6e332d39df --- /dev/null +++ b/website/static/security/patches/EN-26:02/arm64-14.patch @@ -0,0 +1,66 @@ + arm64: Correctly align the SVE signal context + + The SVE signal context needs to be correctly aligned. Fix this by + creating a new macro to calculate the needed size to provide this + alignment, and use it when setting and checking the saved SVE signal + context. + + Approved by: so + Security: FreeBSD-EN-26:02.arm64 + Reported by: cperciva + Reviewed by: cperciva, markj + Sponsored by: Arm Ltd + Differential Revision: https://reviews.freebsd.org/D54396 + + (cherry picked from commit a9e77eb7016df70723c208fc09fbd01ec23a732d) + (cherry picked from commit bcd6bb8067d13d28d13a309e32818cda9e0d29ff) +--- sys/arm64/arm64/exec_machdep.c.orig ++++ sys/arm64/arm64/exec_machdep.c +@@ -60,6 +60,10 @@ + #include <machine/vfp.h> + #endif + ++#define CTX_SIZE_SVE(buf_size) \ ++ roundup2(sizeof(struct sve_context) + (buf_size), \ ++ _Alignof(struct sve_context)) ++ + _Static_assert(sizeof(mcontext_t) == 880, "mcontext_t size incorrect"); + _Static_assert(sizeof(ucontext_t) == 960, "ucontext_t size incorrect"); + _Static_assert(sizeof(siginfo_t) == 80, "siginfo_t size incorrect"); +@@ -545,8 +549,7 @@ + + buf_size = sve_buf_size(td); + /* Check the size is valid */ +- if (ctx.ctx_size != +- (sizeof(sve_ctx) + buf_size)) ++ if (ctx.ctx_size != CTX_SIZE_SVE(buf_size)) + return (EINVAL); + + memset(pcb->pcb_svesaved, 0, +@@ -689,7 +692,7 @@ + { + struct sve_context ctx; + struct pcb *pcb; +- size_t buf_size; ++ size_t buf_size, ctx_size; + vm_offset_t ctx_addr; + + pcb = td->td_pcb; +@@ -700,14 +703,15 @@ + MPASS(pcb->pcb_svesaved != NULL); + + buf_size = sve_buf_size(td); ++ ctx_size = CTX_SIZE_SVE(buf_size); + + /* Address for the full context */ +- *addrp -= sizeof(ctx) + buf_size; ++ *addrp -= ctx_size; + ctx_addr = *addrp; + + memset(&ctx, 0, sizeof(ctx)); + ctx.sve_ctx.ctx_id = ARM64_CTX_SVE; +- ctx.sve_ctx.ctx_size = sizeof(ctx) + buf_size; ++ ctx.sve_ctx.ctx_size = ctx_size; + ctx.sve_vector_len = pcb->pcb_sve_len; + ctx.sve_flags = 0; + diff --git a/website/static/security/patches/EN-26:02/arm64-14.patch.asc b/website/static/security/patches/EN-26:02/arm64-14.patch.asc new file mode 100644 index 0000000000..bdb50b1ce1 --- /dev/null +++ b/website/static/security/patches/EN-26:02/arm64-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NC0ACgkQbljekB8A +Gu9schAAsCCVFg8KhVms97fb/78k2BWl7YkdPAU18BhNEHKPGUdeUD7Jml6UpH+h +2563WXGeemD67c9tQyb5zufffgsuWjNDYveF24AIo/Z6Eg7ulXtE0Bup2q5p8sNo +joqlyfcGpM1hr/lKad2cz4xVDvx4UwPRjo+b3j0BxUVXrln+Doqo39lUf9+F+d7U +Qdkm5u9mkftIQSbxTrwjvD+/nLQkvrfpZ/fECgr0T6Fu29zHHgf6jJIYhPUvydpL +0p7Y6n/7X80NorojvoxV2qQbA6mjPUJBCz7pauqzyQKp04WD+iFg9lbIx0K4VEb7 +eopsg3WgReBaQnX/jFRzpAMN3dtNsbU4DmbAGGheO84nn+VajD5AJK/lgJCFAY8b +Tb7TtYpPOcdQqWVXK+jjWaaeZvqoP8vwDk7e4ZLt2TrpvnrUDdv2xbmTlyY4Ko5E +uyqVOmox4zx1S5MkZ5d0ugDYFfhjJMr2U6/wZAxfS5m1LpsCqAAdtJzHcMJI5wcF +hGIgsJIn6+J8VcfTGIwur42RV7O9CXpjlEnVkkg2co5uG5l5hhhkBDYnnVbJeHKs +hUtN0FUYnJRa0rxciMpM9HM5sSpPkrhGXyC2kiqFNpP+c7eQXOQFs4kbgl15wttJ +fe+La9ZN1GYDyD8xAUXbnR8DxNUtSJoAwmLUZ1TLSD5VXReGiI0= +=FODI +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:02/arm64-15.patch b/website/static/security/patches/EN-26:02/arm64-15.patch new file mode 100644 index 0000000000..ceda6b666e --- /dev/null +++ b/website/static/security/patches/EN-26:02/arm64-15.patch @@ -0,0 +1,66 @@ + arm64: Correctly align the SVE signal context + + The SVE signal context needs to be correctly aligned. Fix this by + creating a new macro to calculate the needed size to provide this + alignment, and use it when setting and checking the saved SVE signal + context. + + Approved by: so + Security: FreeBSD-EN-26:02.arm64 + Reported by: cperciva + Reviewed by: cperciva, markj + Sponsored by: Arm Ltd + Differential Revision: https://reviews.freebsd.org/D54396 + + (cherry picked from commit a9e77eb7016df70723c208fc09fbd01ec23a732d) + (cherry picked from commit 683decf362ce0bbfd9ff917618f3e181bc8f1cd0) +--- sys/arm64/arm64/exec_machdep.c.orig ++++ sys/arm64/arm64/exec_machdep.c +@@ -60,6 +60,10 @@ + #include <machine/vfp.h> + #endif + ++#define CTX_SIZE_SVE(buf_size) \ ++ roundup2(sizeof(struct sve_context) + (buf_size), \ ++ _Alignof(struct sve_context)) ++ + _Static_assert(sizeof(mcontext_t) == 880, "mcontext_t size incorrect"); + _Static_assert(sizeof(ucontext_t) == 960, "ucontext_t size incorrect"); + _Static_assert(sizeof(siginfo_t) == 80, "siginfo_t size incorrect"); +@@ -585,8 +589,7 @@ + + buf_size = sve_buf_size(td); + /* Check the size is valid */ +- if (ctx.ctx_size != +- (sizeof(sve_ctx) + buf_size)) ++ if (ctx.ctx_size != CTX_SIZE_SVE(buf_size)) + return (EINVAL); + + memset(pcb->pcb_svesaved, 0, +@@ -729,7 +732,7 @@ + { + struct sve_context ctx; + struct pcb *pcb; +- size_t buf_size; ++ size_t buf_size, ctx_size; + vm_offset_t ctx_addr; + + pcb = td->td_pcb; +@@ -740,14 +743,15 @@ + MPASS(pcb->pcb_svesaved != NULL); + + buf_size = sve_buf_size(td); ++ ctx_size = CTX_SIZE_SVE(buf_size); + + /* Address for the full context */ +- *addrp -= sizeof(ctx) + buf_size; ++ *addrp -= ctx_size; + ctx_addr = *addrp; + + memset(&ctx, 0, sizeof(ctx)); + ctx.sve_ctx.ctx_id = ARM64_CTX_SVE; +- ctx.sve_ctx.ctx_size = sizeof(ctx) + buf_size; ++ ctx.sve_ctx.ctx_size = ctx_size; + ctx.sve_vector_len = pcb->pcb_sve_len; + ctx.sve_flags = 0; + diff --git a/website/static/security/patches/EN-26:02/arm64-15.patch.asc b/website/static/security/patches/EN-26:02/arm64-15.patch.asc new file mode 100644 index 0000000000..5d282250e4 --- /dev/null +++ b/website/static/security/patches/EN-26:02/arm64-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NC4ACgkQbljekB8A +Gu8ifg//duOg4dSF2xAJp6zziv5AC8SSZ1lUnVL5gTICnif5CKfbe4lUgGDBvqdC +dT6elKqo6alRfoSNfLXHzp8nBLqcdA2P/twt/KrqTSojKERlaXsvMr0XZxegIOuK +kBKsxYJpcNJtIuWU9GiTQ33wyUMRIa8nfulLYDzSS/Wovtec6JuF0F61qkVao0pU +AZ7OT+5G9x9cWc3SHrSSuXD3lk1Xn7hGTq/uNGlFuAJ6QgRthIMiYKz2ujJAjPD0 +x8PjLOdCwJG4btgL7ra0YC3N/3rYq5hKtuEUPrXNVxXfP/Xh4KO7/lfI7mRryNRx +s3H0TDoS3CQ0rAkBg/XyaIIv4RgdCBGDU7sB81DA0PluiFjXHbrgsN2uQyQhMf/t +dqsSUuJplithh/eZqCPBezOnMusDm3h39evThNoKtTck/bZFMQSwIBU/baTXp6JL +mE7IIH9zcoTpDKCTIMboEGmAT1bxJbfaMQp3f4IYnwSDe0BsASRk5iQn9YKIxHZ9 +SGlTPJiTbQMbnRzi3mM6DBMQKkNKD2oyJGAh3k++I0BzBa9AVNr7VC/Ah6erOtiO +QqCjo1453pq1CLujHj4EMau/X9YtTAAZUVgv4vncYWQ2srt3bu8uqNayrVmZXIwc +pZnVU6lsVLcydzLX3GOlJK9ylxnVyKvIb0r3eUpU1N/mBVuQGOc= +=n+lg +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:03/vm-13.patch b/website/static/security/patches/EN-26:03/vm-13.patch new file mode 100644 index 0000000000..501a6edf98 --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-13.patch @@ -0,0 +1,62 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -137,6 +137,7 @@ + vm_object_t object; + vm_pindex_t pindex; + vm_page_t m; ++ bool m_needs_zeroing; + + /* Top-level map object. */ + vm_object_t first_object; +@@ -242,6 +243,7 @@ + fault_deallocate(struct faultstate *fs) + { + ++ fs->m_needs_zeroing = true; + fault_page_release(&fs->m_cow); + fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1086,7 +1088,7 @@ + /* + * Zero the page if necessary and mark it valid. + */ +- if ((fs->m->flags & PG_ZERO) == 0) { ++ if (fs->m_needs_zeroing) { + pmap_zero_page(fs->m); + } else { + VM_CNT_INC(v_ozfod); +@@ -1200,6 +1202,7 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1459,6 +1462,7 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; ++ fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + faultcount = 0; +--- sys/vm/vm_object.c.orig ++++ sys/vm/vm_object.c +@@ -2123,7 +2123,7 @@ + (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, + ("vm_object_page_remove: illegal options for object %p", object)); + if (object->resident_page_count == 0) +- return; ++ goto remove_pager; + vm_object_pip_add(object, 1); + again: + p = vm_page_find_least(object, start); +@@ -2199,6 +2199,7 @@ + } + vm_object_pip_wakeup(object); + ++remove_pager: + vm_pager_freespace(object, start, (end == 0 ? object->size : end) - + start); + } diff --git a/website/static/security/patches/EN-26:03/vm-13.patch.asc b/website/static/security/patches/EN-26:03/vm-13.patch.asc new file mode 100644 index 0000000000..ae3faa694e --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDAACgkQbljekB8A +Gu8Dow//b9q09OnhR/Upz9IEMGQ7w9vHjgDs4Nulcd6BbbkKl4lttspofZKV4xLp +BT53QWDVDQ/jxy5srNdg4mXEQ0PbX9jGDc83yAu8kSDs50u1o4+TzZblxetHSAYs +Z4S1f+nj4k1lBHBGnsOxWXr/ITdHH4iaNhKKDPkzddKKQSw2dT4zOD2YY6M0Qw8w +xfzYILZK2HFclnw4ly6Q8clvGwsmmsFaQ1QvL230wmmQI3BzO393aa4Wh39pc0v+ +gKU1/JHNbRv3SX06ehkJCs7zMtpVV4GFoodCwftCCvpmJKQFpd+3/wH2jDNSYQl+ +ilYllpFSzaf0uElJpSiHNxCiHqHjXo/m09fw24j+Xd9DnQ/8qMyJDnUDQh68TeOW +gBqH8/w8t7PmYj+rANa4vKoCbAbxygzSdFGFcG1Ii737j5z9aJVt8GfIxhZ/+nqt +so9riRbaMkkTs9FzjQm/uAh0OFxpzAMcY8xW8fPn4L/Fz5g96f8/IdtD8PDyAj1R +cCd+/BHr1kaFOwbXxnQYvAAv32lop7Y+TkrzEOEn2WKgyUTNBXa0UGcR6pBG9feN ++3wnDzaurzX77duEugJKZIU2d7nJhRQcZk1vVbvQ/1NUdXjUkFQWlU1aTxgzdcGc +owp/eJtpbREYOVosh/lV1LrrVjweR15N/ZLsle/bvA2l2zU8W84= +=fIgL +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:03/vm-14.patch b/website/static/security/patches/EN-26:03/vm-14.patch new file mode 100644 index 0000000000..b899a0db84 --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-14.patch @@ -0,0 +1,62 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -139,6 +139,7 @@ + vm_object_t object; + vm_pindex_t pindex; + vm_page_t m; ++ bool m_needs_zeroing; + + /* Top-level map object. */ + vm_object_t first_object; +@@ -265,6 +266,7 @@ + vm_fault_deallocate(struct faultstate *fs) + { + ++ fs->m_needs_zeroing = true; + vm_fault_page_release(&fs->m_cow); + vm_fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1172,7 +1174,7 @@ + /* + * Zero the page if necessary and mark it valid. + */ +- if ((fs->m->flags & PG_ZERO) == 0) { ++ if (fs->m_needs_zeroing) { + pmap_zero_page(fs->m); + } else { + VM_CNT_INC(v_ozfod); +@@ -1286,6 +1288,7 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1553,6 +1556,7 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; ++ fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + fs.can_read_lock = true; +--- sys/vm/vm_object.c.orig ++++ sys/vm/vm_object.c +@@ -2088,7 +2088,7 @@ + (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, + ("vm_object_page_remove: illegal options for object %p", object)); + if (object->resident_page_count == 0) +- return; ++ goto remove_pager; + vm_object_pip_add(object, 1); + again: + p = vm_page_find_least(object, start); +@@ -2164,6 +2164,7 @@ + } + vm_object_pip_wakeup(object); + ++remove_pager: + vm_pager_freespace(object, start, (end == 0 ? object->size : end) - + start); + } diff --git a/website/static/security/patches/EN-26:03/vm-14.patch.asc b/website/static/security/patches/EN-26:03/vm-14.patch.asc new file mode 100644 index 0000000000..32bf20325b --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDEACgkQbljekB8A +Gu+ldBAAgne5Rzok3ZXMDhJWyi0QaDvuyWAmjyiQXJMNIdf5yT/NjDaRXERolncI +0eG1YKiMW0iDrTEjuuTA3mzQ8vUcsgE5FC/dDwyHEyXDwYS+eM8A0bkl1Iz/JpmT +s+f48TrL6Ln6CxN+ZcOES9IDb3tXHfWqjwm4BcWwsyItTV13fbHkT8+NyCYyOjXo +idEadNTbKKweotKar5Mjiqfsh75i26Kfjwa7ejx1RRIBOn6mZ/rKjfhjXdnn9NTH +phGAPuEk3NU9qkaFoSxliPsL1nlHMh8vyN5LBkmcv0enaCbBf3iJUgW9+sb+UmqP +2SfbswHENGsLLx2Thp+JpgM5XNghM8HV+fMj4zCKETiXmA8QTHqT7XH6s+gSCfBz +mddktQHTorjTHtkNgMudwH1Z/c/x9bDEfg4xfT+0ZLkm5hCaikwz256NxrH0j16C +EcvPdSPv89m7pF50/VyO1p6RXykOLSw8OKp7mV7z/jdnI9yXKOY/YwEBjL8iaeQO +7XER1w9o0btvbvNvhfXlWqpshK96i1dTt3rAyjp74h4U3KkDP4FfhrDdhFlgFJ2E +15dog3fHdrIDa9/vzHBG3h/MAzsGrA4gAzIqw2zb+s9q0Tfv0CYzkwd4RXpwmnkX +fIrHoanV/cD+mjuouXVfXCZKRH30g8m6PmCxtonaZj3nv1AvsiE= +=rFz7 +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:03/vm-15.patch b/website/static/security/patches/EN-26:03/vm-15.patch new file mode 100644 index 0000000000..6acd7d3766 --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-15.patch @@ -0,0 +1,62 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -138,6 +138,7 @@ + vm_object_t object; + vm_pindex_t pindex; + vm_page_t m; ++ bool m_needs_zeroing; + + /* Top-level map object. */ + vm_object_t first_object; +@@ -264,6 +265,7 @@ + vm_fault_deallocate(struct faultstate *fs) + { + ++ fs->m_needs_zeroing = true; + vm_fault_page_release(&fs->m_cow); + vm_fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1181,7 +1183,7 @@ + /* + * Zero the page if necessary and mark it valid. + */ +- if ((fs->m->flags & PG_ZERO) == 0) { ++ if (fs->m_needs_zeroing) { + pmap_zero_page(fs->m); + } else { + VM_CNT_INC(v_ozfod); +@@ -1296,6 +1298,7 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1586,6 +1589,7 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; ++ fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + fs.can_read_lock = true; +--- sys/vm/vm_object.c.orig ++++ sys/vm/vm_object.c +@@ -1988,7 +1988,7 @@ + (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, + ("vm_object_page_remove: illegal options for object %p", object)); + if (object->resident_page_count == 0) +- return; ++ goto remove_pager; + vm_object_pip_add(object, 1); + vm_page_iter_limit_init(&pages, object, end); + again: +@@ -2061,6 +2061,7 @@ + } + vm_object_pip_wakeup(object); + ++remove_pager: + vm_pager_freespace(object, start, (end == 0 ? object->size : end) - + start); + } diff --git a/website/static/security/patches/EN-26:03/vm-15.patch.asc b/website/static/security/patches/EN-26:03/vm-15.patch.asc new file mode 100644 index 0000000000..be36220124 --- /dev/null +++ b/website/static/security/patches/EN-26:03/vm-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDMACgkQbljekB8A +Gu+6BA/9FHXJvmYBzQOU8GWQSVOnrJFkJDtFCr0u2LXumX1lDJQxAzCJL9qqe1M4 +EM3B4nCGEfsD3gtjBlemrwCDNa/V7sdB4I3FSoFBIQvG9oQaLQPmqLTckI6mC5uH +zAgFI9Q9gRUzWe47Qfx+HfXbMRQTldDxBb8koi3Z92TMOKirs3xfRULH7xjlVXdu +ZzXMJLKRTmAOkaU2vHZ9ERg4vLdTarKyIhvYwH4jP+pY7+9V/x+Eqw5Oua7OpQhw +i/qp9BRLWpSpG8M6QiDesHDBR2XUvVb80Glk7PIOV4BBhSxR2SG0UxJbxh/hp/ZB +m48CRjjGoGKY2sTBhg9qKKJ/OxpQANa22cdai9zAcHXp8M+l0ceQnuBqAQh9DpEr +PEXj2N/Ze8D7sVG26+j3CqGAHHHpJXdGndVqOUGTWvp4fdCdgGHc1j/wAThssk3V +Wdj2BFM7CmeKGqLGIMajvQPxHImB1j2LazsIzSvIw9aQNYo4JX6COMbz2HIFkRji +bPfqXpscMK8fXYgAznz6W8soBAp1Pxbi1o2M8M49ldNZNK3TwrgP4Kolpg6zJKh8 +jOvFbjSa5JsI9u5XJvxc+Vge/lY+IWcb0kQFf8qp/CZ0+CQn/Q4vOf7RVMV/Aojc +84Jsz/at2yJa6r3YL+NfwbGSeG95+0OECK1z360jWFk9uW9PlFw= +=EnUH +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:04/arm64.patch b/website/static/security/patches/EN-26:04/arm64.patch new file mode 100644 index 0000000000..49eab05c0b --- /dev/null +++ b/website/static/security/patches/EN-26:04/arm64.patch @@ -0,0 +1,22 @@ +--- sys/arm64/arm64/vfp.c.orig ++++ sys/arm64/arm64/vfp.c +@@ -934,6 +934,9 @@ + + pcb = td->td_pcb; + ++ if (td == curthread && (pcb->pcb_fpflags & PCB_FP_STARTED) != 0) ++ vfp_save_state(td, pcb); ++ + /* If there is no SVE support in HW then we don't support NT_ARM_SVE */ + if (pcb->pcb_sve_len == 0) + return (false); +@@ -955,9 +958,6 @@ + KASSERT(*sizep == sizeof(struct svereg_header) + buf_size, + ("%s: invalid size", __func__)); + +- if (td == curthread && (pcb->pcb_fpflags & PCB_FP_STARTED) != 0) +- vfp_save_state(td, pcb); +- + header = buf; + memset(header, 0, sizeof(*header)); + diff --git a/website/static/security/patches/EN-26:04/arm64.patch.asc b/website/static/security/patches/EN-26:04/arm64.patch.asc new file mode 100644 index 0000000000..8c0aaee022 --- /dev/null +++ b/website/static/security/patches/EN-26:04/arm64.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmLdZEACgkQbljekB8A +Gu8lYQ//XPC/xi9ll2qHWYjM4PTuwuRA5qepfQ0hUJUMXmA6XNYGhnC7npNuvuw3 +njSjg+BkJQoXSSGCRBEBF+eVdbm/QPIgBt9snxW3WF7BRe4YrSKGl8apblgfjkEw +/6eJHVFrTFFVwKskcwzyHGNuGr5I3Gg1wahKuicLm3FES5+niQ5HW0C/Jfb3VDtX +ZMxZL8PLUpDwuwK475fRsLHj5w8Cz/DzltGSSDGjmSKeho6WF8bs9z4nJT5BEr5s +1FmbCTuaUYpmHRcCpHNgCAOVrJdi59VQz/t+tMLtMGLI5G+val6RLqX/MjnZTdAC +LaelwffoxTSrMjUd3bsqlXEjk44TMT/Ze+aHUjw0CMlG0Eb+69tc1Ld67qXBaw2H +/bAMB6BMpSG0tpxEGjV+RqVaU3CE1F8udcDeqOEWwzTm5pipl7N4flELyt+v29/1 +kqnyOOT6DUl8Gfvz65791/4THMv6wVpoXzL9bXv6N/OmjoiVarVMIPugHllOrAhZ +OdOmRZj9Qqp/VJTYvuIbheP0uHwdcR6Nhest6TAoh30lg/B9bQTs70mCkv+fQ5sB +knw2cDADpS1n3RMKGLKfzNgkKSUExnV+zDDg7+VK7HXdbq6TH6L2bYVZeDSAs/VE +K06QlnExJzo7gJgUsBlKyBgGMfS6Db/i9Mtb4Kk+H2qb66cZjlk= +=8f4X +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:05/vm-13.patch b/website/static/security/patches/EN-26:05/vm-13.patch new file mode 100644 index 0000000000..17aea3c29f --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-13.patch @@ -0,0 +1,37 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -242,8 +242,6 @@ + static void + fault_deallocate(struct faultstate *fs) + { +- +- fs->m_needs_zeroing = true; + fault_page_release(&fs->m_cow); + fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1202,7 +1200,8 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } +- fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; ++ if (fs->object == fs->first_object) ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1462,7 +1461,6 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; +- fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + faultcount = 0; +@@ -1470,6 +1468,7 @@ + + RetryFault: + fs.fault_type = fault_type; ++ fs.m_needs_zeroing = true; + + /* + * Find the backing store object and offset into it to begin the diff --git a/website/static/security/patches/EN-26:05/vm-13.patch.asc b/website/static/security/patches/EN-26:05/vm-13.patch.asc new file mode 100644 index 0000000000..03a52af1a4 --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoZsACgkQbljekB8A +Gu8G9xAAr5GsurThSC4pSyxC7DbYuXK9YZzMlPH8vRR03O3fF/j59FYQrbzh+ZmC +YsBjOh6p1ljOZrO3VWohjr7VzLtALgifKT2HL8Rn3Etmlpf5TUnEkjksFTSRhVZZ +jOKow4pyR95n/7eC3R51sz5euxSvlqMfLYlmx32f1gZ6TEAOaTUjtCneQ1QCvLNq +6lrtvMIs1BUkG6/aAVGe+GvkpBLuuoT5nhXRHHbHICR5mtgmf26YxbttLHvSATJn +NYISF8yiesjVXy4uU7lFBmRQ7ZZmBtltsULjQ3uNiksw04+RTNRS/QNVzI7G4ha6 +gHfSKE3F4lb5vuxKGXKXwXkwXF90fO5436HgWlePjZGn+GFPA/mCwKrJVa4MawfZ +LE/iEhu60wncTT/ivjdEeg8bcvQlG951yif6z2aqwoIz0BD650ufllxpIINCZdsW +Iz8Yw8z2uzkyvPamvSQlAN7JENStza/pbdfnu3GZgwrjLJtf+RJon4F/v1JzBtSG +P/8s1PReEyaiIDOifB0NSpopTW6satPC1dThg1LW2Y+lfyy6U3rCgKXHCzPGjQsI +ZV/90eUDX+uwfM9TvRo8znt/zFqh2Q90pr/qbJUdpZsTsNxC/ZEN0AzVkrrwp46/ +v/q1wJfmNaQfYSQLc8y+FmhwvesvDLy/dxy8eq0w8CqUqqBa19s= +=csNp +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:05/vm-14.patch b/website/static/security/patches/EN-26:05/vm-14.patch new file mode 100644 index 0000000000..2e6979c244 --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-14.patch @@ -0,0 +1,37 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -272,8 +272,6 @@ + static void + vm_fault_deallocate(struct faultstate *fs) + { +- +- fs->m_needs_zeroing = true; + vm_fault_page_release(&fs->m_cow); + vm_fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1321,7 +1319,8 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } +- fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; ++ if (fs->object == fs->first_object) ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1653,7 +1652,6 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; +- fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + fs.can_read_lock = true; +@@ -1662,6 +1660,7 @@ + + RetryFault: + fs.fault_type = fault_type; ++ fs.m_needs_zeroing = true; + + /* + * Find the backing store object and offset into it to begin the diff --git a/website/static/security/patches/EN-26:05/vm-14.patch.asc b/website/static/security/patches/EN-26:05/vm-14.patch.asc new file mode 100644 index 0000000000..940e150b3d --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoZwACgkQbljekB8A +Gu9FrxAAxQaGukd6JDEY/DliFPK97voostmMZD8S1Yn4FamsDVC+3qrkggPSu4TP +x10jLXIYIO2LpkVDabAJNA3tHgKzuy1Z3ORjudYTcodNIaab1JUWfgAw0Lw7V4g5 +Xl6OWHBml8fpzekxE35/x4MLXeokRZz8aNZUWFZbmQ5gA+gg1QpzNMmpytk6l6FM +Sp2nUEMUOsa+VXJBSIktgVWErtQ8n0NjwlKo69qHZwLyWtuprf5iMI2LZ5DYUQns +wjr/gvZe8Du8/cwgzeDuPRuTkDAxvfh7JyDhpgm26Tp4weXMuBOqBK9jycp6jh/y +GxoFcp/DL5EjqK06N4Ht8ZheNKJOdSLkTnQe3khgVXM01TN+VtwpsN4GfLmpsrt+ +7NesWyiW3HgTMSL6ulUT5HaE2q/8IG+FKYLQDCoBRiu7gqQkEBsX/72V0byxlZ0W +K+c/ASELy53ZF7UqBkdA/+4qWFxO9qTKiZrwmNM8g0Ss1bA72WEmk+a766YV4ioM +fWpyP9+Py2Rth5B8DyzgIX7JkstFxZNhg+oN0aQ6khIzeoLiahjO+7CKaYWIqMVh +TXKRJJyAwXj6cllekELQmwG97JeKbK22jgqEvzDxA4HWASjXjpwbNtrrOJNPtpeh +QbpzHOLM++6/LmtUsQaLD+4DJyYYBeFI1daSxe6X19gHubbhgIU= +=19Gd +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:05/vm-15.patch b/website/static/security/patches/EN-26:05/vm-15.patch new file mode 100644 index 0000000000..e18deab8df --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-15.patch @@ -0,0 +1,37 @@ +--- sys/vm/vm_fault.c.orig ++++ sys/vm/vm_fault.c +@@ -273,8 +273,6 @@ + static void + vm_fault_deallocate(struct faultstate *fs) + { +- +- fs->m_needs_zeroing = true; + vm_fault_page_release(&fs->m_cow); + vm_fault_page_release(&fs->m); + vm_object_pip_wakeup(fs->object); +@@ -1370,7 +1368,8 @@ + vm_waitpfault(dset, vm_pfault_oom_wait * hz); + return (FAULT_RESTART); + } +- fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; ++ if (fs->object == fs->first_object) ++ fs->m_needs_zeroing = (fs->m->flags & PG_ZERO) == 0; + fs->oom_started = false; + + return (FAULT_CONTINUE); +@@ -1705,7 +1704,6 @@ + fs.fault_flags = fault_flags; + fs.map = map; + fs.lookup_still_valid = false; +- fs.m_needs_zeroing = true; + fs.oom_started = false; + fs.nera = -1; + fs.can_read_lock = true; +@@ -1714,6 +1712,7 @@ + + RetryFault: + fs.fault_type = fault_type; ++ fs.m_needs_zeroing = true; + + /* + * Find the backing store object and offset into it to begin the diff --git a/website/static/security/patches/EN-26:05/vm-15.patch.asc b/website/static/security/patches/EN-26:05/vm-15.patch.asc new file mode 100644 index 0000000000..66943c60ee --- /dev/null +++ b/website/static/security/patches/EN-26:05/vm-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoZ4ACgkQbljekB8A +Gu8G6w//TlGub/hDpizdLo4o9UuAjBVG+FNaTl8UErIBIfy/rVIf9KmOIEqA3Boo +CHct4nE0WcWhnkFZsPDsVmyehrpstmeYWNLlJP1gBioaKAd001EJzKxTpoMFq5cC +PuDUtkPN65W13TP7+1lYnv2VSYraJ0NVG0eCfTGm0dISCVUDO35WQTFvXstcbkqm +B8GnJQvG6KzA3ju+IlR1NUf28PfqclIUkty5nGf2P1waN6BLqe4sN3vG2yAgUUnN +38czltWOEwsUcZSWcKv/TsaeIcBKTvcf2EdQ//BmBZNEAhCIXbX7+p1vtD8F2IBx +mBnTsfs/RkLjgundg7L5sD4F61PLAJfS9IkI/ZCi5biouCqr2FQGznV7sUGPNmOf +SxjJ8REj7gdPlv59Kj/J3ydCVig7l6etumpM15bwtZeAW//19bw7ixYmSQa2iXu+ +kEiMl7i9u+/Vcc3KVCwDjov7vsUW4nqTogzhP7XqmMGu0vOigWogH963E3vHh2Gv +4vxVuna1DYkai+x/7F0UfTUVFQpeawDTNURWNKzzaw8rL1OllYUevDfygvpE01Vt +rmQsZUpf5nJus4HmXEIdBRwledtvyOF//+M4ZB1Ggv3ney7+WgGaV1cr1tT6mX6j +dvXJHwQEEzl4qe99AfyaRFGaMp1vb9nBE2smJOsytneqV55wC7M= +=R9hc +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:06/timerfd.patch b/website/static/security/patches/EN-26:06/timerfd.patch new file mode 100644 index 0000000000..75cbad7be3 --- /dev/null +++ b/website/static/security/patches/EN-26:06/timerfd.patch @@ -0,0 +1,39 @@ +--- sys/kern/sys_timerfd.c.orig ++++ sys/kern/sys_timerfd.c +@@ -393,23 +393,25 @@ + timerfd_expire(void *arg) + { + struct timerfd *tfd = (struct timerfd *)arg; +- struct timespec uptime; ++ sbintime_t exp, interval, now, next, diff; + + ++tfd->tfd_count; + tfd->tfd_expired = true; + if (timespecisset(&tfd->tfd_time.it_interval)) { ++ exp = tstosbt(tfd->tfd_time.it_value); ++ interval = tstosbt(tfd->tfd_time.it_interval); ++ now = sbinuptime(); ++ next = now + interval; ++ + /* Count missed events. */ +- nanouptime(&uptime); +- if (timespeccmp(&uptime, &tfd->tfd_time.it_value, >)) { +- timespecsub(&uptime, &tfd->tfd_time.it_value, &uptime); +- tfd->tfd_count += tstosbt(uptime) / +- tstosbt(tfd->tfd_time.it_interval); ++ if (now > exp) { ++ diff = now - exp; ++ tfd->tfd_count += diff / interval; ++ next -= diff % interval; + } +- timespecadd(&tfd->tfd_time.it_value, +- &tfd->tfd_time.it_interval, &tfd->tfd_time.it_value); +- callout_schedule_sbt(&tfd->tfd_callout, +- tstosbt(tfd->tfd_time.it_value), +- 0, C_ABSOLUTE); ++ ++ callout_schedule_sbt(&tfd->tfd_callout, next, 0, C_ABSOLUTE); ++ tfd->tfd_time.it_value = sbttots(next); + } else { + /* Single shot timer. */ + callout_deactivate(&tfd->tfd_callout); diff --git a/website/static/security/patches/EN-26:06/timerfd.patch.asc b/website/static/security/patches/EN-26:06/timerfd.patch.asc new file mode 100644 index 0000000000..dd6ba3a15a --- /dev/null +++ b/website/static/security/patches/EN-26:06/timerfd.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaAACgkQbljekB8A +Gu9mfhAAtH/CEXo4l2ZgJJwWP58rIkiySYrNcFny8Kh6OjTfKy8hBl6UuSPto/9G +tvsmpCmiOtkPbNxvPibXuP4CEoXksTkfTyvmb2opDIK/ZUjGpFS+eBXRnoUgjdaU +LZMdHU33LD3RX+qirJiOgit2bajsAHLknjiqR+gpTZuW2TwWGzHOsITPt/eJ4Fbd +cjYW1nfoXKj7kIErY9SWBYDlKBVA+sD5nQ8c4b7VVuWoTR2iLREVef/QJQCrCeQe +JMSW4nKVZOEThLQarhA3fF4XKw7DXB/uFxyXtknZapCW/kDOc/gAKEwouoaVARff +ACD8drBEqUqiNmS/QWeRbFEtiauw03S+sHiR5uzsognQFpttZNSpfGxckr9viI+9 +uU7N7cyXep7snwcFr+7P3nHiJ9+1phNT0ho3y4cpVSGk1QPhNJlLKtDLYYpOU/lD +uEroV8tgs97CKnOG2JqwrgSiFQwbpJu8uhsPEQA04AwJbtkd8efCfGyt9xtiEB8Z +tnj4iFqEbacyZzN+qGH+7RlFFtd7rmfpfQXwY7RWjrWc984EVWm2CleOpURZpeT/ +7odnjn8Rr5vJVgWad5uH90dW8kZOxC+MWZJyPxD5/5JyQpdBHI7Gfzs0Yo8q1VqP +rUHde/b6lEuPd5TrkQ4xtgwN6Em0LMw7r7cy88Q8WR1YI59YIWU= +=Mu/l +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:07/pkgbase.patch b/website/static/security/patches/EN-26:07/pkgbase.patch new file mode 100644 index 0000000000..83ef38f19f --- /dev/null +++ b/website/static/security/patches/EN-26:07/pkgbase.patch @@ -0,0 +1,22 @@ +--- release/packages/generate-set-ucl.lua.orig ++++ release/packages/generate-set-ucl.lua +@@ -16,7 +16,7 @@ + local ucl = require("ucl") + + -- This parser is the output UCL we want to build. +-local parser = ucl.parser() ++local parser = ucl.parser(0) + + if #arg < 1 then + io.stderr:write(arg[0] .. ": missing template filename\n") +--- release/packages/generate-ucl.lua.orig ++++ release/packages/generate-ucl.lua +@@ -124,7 +124,7 @@ + local pkgversion = nil + + -- This parser is the output UCL we want to build. +-local parser = ucl.parser() ++local parser = ucl.parser(0) + + -- Set any $VARIABLES from the command line in the parser. This causes ucl to + -- automatically replace them when we load the source ucl. diff --git a/website/static/security/patches/EN-26:07/pkgbase.patch.asc b/website/static/security/patches/EN-26:07/pkgbase.patch.asc new file mode 100644 index 0000000000..e5d5ae54ab --- /dev/null +++ b/website/static/security/patches/EN-26:07/pkgbase.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaIACgkQbljekB8A +Gu96SxAAjYt9UeZq5utoATKbYq9fEz+mi+wIiZG3Fa7RwLX7mL5HsslHGedgWN/B +Xy5IvCSs48Yg+xQctFbdmy20iW4kgxA9/EbZHx6jtUcMp8ieEpO+yAuISjkGyUp8 +XE7bmJun3StWZKuh4gKaGs+6dJJRgdQKQ36Gvd/jY+0rhixMSW4OK/bXetoe6/5g +ClgeawtzL6Iz0SCMnKtKuUHjePh8YoX2NHt8skWTIGy7tILSVq8Vd2LI2KjzzZBg +CYulcms96DfICYmXVJFNcP2qcVRtXfqMHAEekSgijQ8Mxj6+E1xwSmsuSKPzby7b +eyeXiI4o2w8p1oSWaxE6c5yD4WfeEgjrux1kQU9o+JFkMMjSfKLshijkVp6JqJWq +BK6f/Mngo2e3okOF1eNSxAp0BFfnIpyI2AVCBqqqqj8QF6QaRxRS7vtwxBp+JTc6 +nFsMLyIzuAb2vJCpRTJvmqf4UK93lS3tETS94OQilhGncuMQSE/Rp7jO8diquqrC +d6jsKtN6GKx8mNaLcVb7xmyFTYZ0DleD/dsFQ3hB2zfe1BskBvgmmBHZ5ojtXKoi +N99vABc5B1WAqda6rTnJUt3g7CbF9ATIAZ44sd14hLJEYz5c7GIQDFDSFZpnR+2Y +kD7EySAxXhW9J8Wl6n6ggxEFuikASF761K2ueu7KBWz9a3Ei7gg= +=ma0B +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:08/pf.patch b/website/static/security/patches/EN-26:08/pf.patch new file mode 100644 index 0000000000..badbc533dd --- /dev/null +++ b/website/static/security/patches/EN-26:08/pf.patch @@ -0,0 +1,69 @@ +--- sys/netpfil/pf/pf_ioctl.c.orig ++++ sys/netpfil/pf/pf_ioctl.c +@@ -1345,9 +1345,7 @@ + PF_MD5_UPD(pfr, addr.iflags); + break; + case PF_ADDR_TABLE: +- if (strncmp(pfr->addr.v.tblname, PF_OPTIMIZER_TABLE_PFX, +- strlen(PF_OPTIMIZER_TABLE_PFX))) +- PF_MD5_UPD(pfr, addr.v.tblname); ++ PF_MD5_UPD(pfr, addr.v.tblname); + break; + case PF_ADDR_ADDRMASK: + case PF_ADDR_RANGE: +--- tests/sys/netpfil/pf/pass_block.sh.orig ++++ tests/sys/netpfil/pf/pass_block.sh +@@ -488,6 +488,47 @@ + pft_cleanup + } + ++atf_test_case "auto_tables" "cleanup" ++auto_tables_head() ++{ ++ atf_set descr 'Test rulesets with different automatic tables' ++ atf_set require.user root ++} ++ ++auto_tables_body() ++{ ++ pft_init ++ ++ epair=$(vnet_mkepair) ++ ifconfig ${epair}b 192.0.2.2/24 up ++ ++ vnet_mkjail alcatraz ${epair}a ++ jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up ++ ++ # Sanity check ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++ ++ jexec alcatraz pfctl -e ++ pft_set_rules alcatraz \ ++ "set ruleset-optimization basic" \ ++ "test_a = \"203.0.113.1 203.0.113.2 203.0.113.3 203.0.113.4 ++ 203.0.113.5 203.0.113.6 203.0.113.7 203.0.113.8 203.0.113.9 ++ 203.0.113.10\"" \ ++ "test_b = \"192.0.2.1 192.0.2.2 192.0.2.3 192.0.2.4 192.0.2.5 ++ 192.0.2.6 192.0.2.7 192.0.2.8 192.0.2.9 192.0.2.10\"" \ ++ "block" \ ++ "pass inet from any to { \$test_a }" \ ++ "pass inet from 198.51.100.1 to 198.51.100.2 no state" \ ++ "pass inet from any to { \$test_b }" ++ ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++} ++ ++auto_tables_cleanup() ++{ ++ pft_cleanup ++} ++ + atf_init_test_cases() + { + atf_add_test_case "enable_disable" +@@ -500,4 +541,5 @@ + atf_add_test_case "optimize_any" + atf_add_test_case "any_if" + atf_add_test_case "addr_range" ++ atf_add_test_case "auto_tables" + } diff --git a/website/static/security/patches/EN-26:08/pf.patch.asc b/website/static/security/patches/EN-26:08/pf.patch.asc new file mode 100644 index 0000000000..725a0c47d2 --- /dev/null +++ b/website/static/security/patches/EN-26:08/pf.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRIbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrva9gP/2E4aiS87JMuY7LyLQgZ +WBVl7aiXahzwnMWYqd7iUxRpHgx/U31bTHyTvBTaPlxnJ2RlMe2FLYCd9vPRVOBc +sLPHIlllAfp8sRjjK1pnaAVi5K5qPULTQrLOQlrPym7GllndPYZyyAV7SajlA41I +GVQFmi6H+jx7D8AEGTwP76KN0FyOkeAAzaeWn3+opcVvYNDDArpBb/4nR1ThuIBs +3IItUFFAIP5IMT3vofXB/bl2I+oXAxD4PMzWKqh52l4dWYRadcQKUBVzOqqARavl +oxbY5jGaoyCEEKgR89o3PMhjMrB+M9IBpILgKUdKgIAz1EAFfIPJkrC6ID4UtToG +ULlHmYXIHi6PXe+2D1L3CpdByffO44szcI7f6GBz9oG/p02k4Flg72C4FHJv6pOZ +xEomz16T1OkiOF5d/haMB/hJWlobM5t7yfPkV2sjrAUuaLHt7kycipA7Ps118Rk/ +CTh/5xUf4iR6MI85vRMZIIaopgNZSYvc2iFyFWwHn//lH4usSil6Ax3xqkcC7UuW +ClXtfVHnR2C2C4EkG8eYhTY35ggmGwDn2XCiQpXlg56oBh62jNHTlVV+1yC9I3XE +tGYCoaZyX1v7/2OXrCVUJQ07VSkuHcIQe/cxUZwMEaJ3M/XaeMNLsP8soO7A/H/q +Z4+JtF+NTWTLDh6SUXxIqd+i +=lWlJ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch b/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch new file mode 100644 index 0000000000..6e6b8e25fc --- /dev/null +++ b/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch @@ -0,0 +1,681 @@ +--- contrib/tzdata/Makefile.orig ++++ contrib/tzdata/Makefile +@@ -66,28 +66,6 @@ + + LOCALTIME= Factory + +-# The POSIXRULES macro controls interpretation of POSIX-like TZ +-# settings like TZ='EET-2EEST' that lack DST transition rules. +-# If POSIXRULES is '-', no template is installed; this is the default. +-# Any other value for POSIXRULES is obsolete and should not be relied on, as: +-# * It does not work correctly in popular implementations such as GNU/Linux. +-# * It does not work even in tzcode, except for historical timestamps +-# that precede the last explicit transition in the POSIXRULES file. +-# Hence it typically does not work for current and future timestamps. +-# If, despite the above, you want a template for handling these settings, +-# you can change the line below (after finding the timezone you want in the +-# one of the $(TDATA) source files, or adding it to a source file). +-# Alternatively, if you discover you've got the wrong timezone, you can just +-# 'zic -p -' to remove it, or 'zic -p rightzone' to change it. +-# Use the command +-# make zonenames +-# to get a list of the values you can use for POSIXRULES. +- +-POSIXRULES= - +- +-# Also see TZDEFRULESTRING below, which takes effect only +-# if POSIXRULES is '-' or if the template file cannot be accessed. +- + + # Installation locations. + # +@@ -170,7 +148,7 @@ + # applications that are not leap second aware, and is closer to unsmeared + # "right" time than unsmeared POSIX time is (e.g., 0.5 vs 1.0 s max error). + +-REDO= posix_right ++REDO= posix_only + + # Whether to put an "Expires" line in the leapseconds file. + # Use EXPIRES_LINE=1 to put the line in, 0 to omit it. +@@ -284,7 +262,10 @@ + # -DHAVE_STRDUP=0 if your system lacks the strdup function + # -DHAVE_STRNLEN=0 if your system lacks the strnlen function+ + # -DHAVE_STRTOLL=0 if your system lacks the strtoll function+ +-# -DHAVE_STRUCT_STAT_ST_CTIM=0 if struct stat lacks a member st_ctim+ ++# -DHAVE_STRUCT_STAT_ST_CTIM=0 if struct stat lacks a status-change member ++# of type struct timespec, so code should use st_ctime instead; ++# but if the status-change member name is st_ctimespec, ++# use -Dst_ctim=st_ctimespec instead (default is guessed)+ + # -DHAVE_STRUCT_TIMESPEC=0 if your system lacks struct timespec+ + # -DHAVE_SYMLINK=0 if your system lacks the symlink function + # -DHAVE_SYS_STAT_H=0 if <sys/stat.h> does not work* +@@ -322,13 +303,13 @@ + # variable, 0 otherwise (default is guessed) + # -DHAVE_SYS_SINGLE_THREADED_H=0 if <sys/single_threaded.h> works, + # 0 otherwise (default is guessed) +-# -DTHREAD_RWLOCK to use read-write locks intead of mutexes. +-# This can improve paralellism and thus save real time ++# -DTHREAD_RWLOCK to use read-write locks instead of mutexes. ++# This can improve parallelism and thus save real time + # if many threads call tzcode functions simultaneously. + # It also costs CPU time and thus energy. + # -DTHREAD_TM_MULTI to have gmtime, localtime, and offtime + # return different struct tm * addresses in different threads. +-# This supports unportable programs that call ++# This supports nonportable programs that call + # gmtime/localtime/offtime when they should call + # gmtime_r/localtime_r/offtime_r to avoid races. + # Because the corresponding storage is freed on thread exit, +@@ -347,10 +328,13 @@ + # -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" + # -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; + # the default is system-supplied, typically "/usr/lib/locale" ++# -DTZ_RUNTIME_LEAPS=0 to disable runtime support for leap seconds. ++# This conforms to POSIX, shrinks tzcode's attack surface, ++# and is more efficient. However, it fails to support Internet ++# RFC 9636's leap seconds. + # -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified +-# DST transitions for proleptic format TZ strings lacking them, +-# in the usual case where POSIXRULES is '-'. If not specified, +-# TZDEFRULESTRING defaults to US rules for future DST transitions. ++# DST transitions for proleptic format TZ strings lacking them. ++# If not specified, it defaults to US rules for future DST transitions. + # This mishandles some past timestamps, as US DST rules have changed. + # It also mishandles settings like TZ='EET-2EEST' for eastern Europe, + # as Europe and US DST rules differ. +@@ -400,12 +384,13 @@ + -Wold-style-definition -Woverlength-strings -Wpointer-arith \ + -Wshadow -Wshift-overflow=2 -Wstrict-overflow \ + -Wstrict-prototypes -Wstringop-overflow=4 \ +- -Wstringop-truncation -Wsuggest-attribute=cold \ ++ -Wsuggest-attribute=cold \ + -Wsuggest-attribute=const -Wsuggest-attribute=format \ + -Wsuggest-attribute=malloc \ + -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure \ + -Wtrampolines -Wundef -Wunused-macros -Wuse-after-free=3 \ + -Wvariadic-macros -Wvla -Wwrite-strings \ ++ -Wzero-as-null-pointer-constant \ + -Wno-format-nonliteral -Wno-sign-compare -Wno-type-limits + # + # If your system has a "GMT offset" field in its "struct tm"s +@@ -723,7 +708,6 @@ + '$(DESTDIR)$(MANDIR)/man3' '$(DESTDIR)$(MANDIR)/man5' \ + '$(DESTDIR)$(MANDIR)/man8' + $(ZIC_INSTALL) -l $(LOCALTIME) \ +- -p $(POSIXRULES) \ + -t '$(DESTDIR)$(TZDEFAULT)' + cp -f $(TABDATA) '$(DESTDIR)$(TZDIR)/.' + cp tzselect '$(DESTDIR)$(BINDIR)/.' +--- contrib/tzdata/NEWS.orig ++++ contrib/tzdata/NEWS +@@ -1,5 +1,137 @@ + News for the tz database + ++Release 2026a - 2026-04-22 23:06:43 -0700 ++ ++ Briefly: ++ British Columbia moved to permanent -07 on 2026-03-09. ++ Some more overflow bugs have been fixed in zic. ++ ++ Changes to future timestamps ++ ++ British Columbia’s 2026-03-08 spring forward was its last ++ foreseeable clock change, as it moved to permanent -07 thereafter. ++ (Thanks to Arthur David Olson.) Although the change to permanent ++ -07 legally took place on 2026-03-09, temporarily model the change ++ to occur on 2026-11-01 at 02:00 instead. This works around a ++ limitation in CLDR v48.2 (2026-03-17). This temporary hack is ++ planned to be removed after CLDR is fixed. ++ ++ Changes to code ++ ++ zic no longer mishandles a last transition to a new time type. ++ ++ zic no longer overflows a buffer when generating a TZ string like ++ "PST-167:59:58PDT-167:59:59,M11.5.6/-167:59:59,M12.5.6/-167:59:59", ++ which can occur with adversarial input. (Thanks to Naveed Khan.) ++ ++ zic no longer generates a longer TZif file than necessary when ++ an earlier time zone abbreviation is a suffix of a later one. ++ As a nice side effect, zic no longer overflows a buffer when given ++ a long series of abbreviations, each a suffix of the next. ++ (Buffer overflow reported by Arthur Chan.) ++ ++ zic no longer overflows an int when processing input like ‘Zone ++ Ouch 2147483648:00:00 - LMT’. The int overflow can lead to buffer ++ overflow in adversarial cases. (Thanks to Naveed Khan.) ++ ++ zic now checks for signals more often. ++ ++ ++Release 2026a - 2026-03-01 22:59:49 -0800 ++ ++ Briefly: ++ Moldova has used EU transition times since 2022. ++ The “right” TZif files are no longer installed by default. ++ -DTZ_RUNTIME_LEAPS=0 disables runtime support for leap seconds. ++ TZif files are no longer limited to 50 bytes of abbreviations. ++ zic is no longer limited to 50 leap seconds. ++ Several integer overflow bugs have been fixed. ++ ++ Changes to past and future timestamps ++ ++ Since 2022 Moldova has observed EU transition times, that is, it ++ has sprung forward at 03:00, not 02:00, and has fallen back at ++ 04:00, not 03:00. (Thanks to Heitor David Pinto.) ++ ++ Changes to data ++ ++ Remove Europe/Chisinau from zonenow.tab, as it now agrees with ++ Europe/Athens for future timestamps. ++ ++ Changes to build procedure ++ ++ The Makefile no longer by default installs an alternate set ++ of TZif files for system clocks that count leap seconds. ++ Install with ‘make REDO=posix_right’ to get the old default, ++ which is rarely used in major downstream distributions. ++ If your system clock counts leap seconds (contrary to POSIX), ++ it is better to install with ‘make REDO=right_only’. ++ This change does not affect the leapseconds file, which is still ++ installed as before. ++ ++ The Makefile’s POSIXRULES option, which was declared obsolete in ++ release 2019b, has been removed. The Makefile’s build procedure ++ thus no longer optionally installs the obsolete posixrules file. ++ ++ Changes to code ++ ++ Compiling with the new option -DTZ_RUNTIME_LEAPS=0 disables ++ runtime support for leap seconds. Although this conforms to ++ POSIX, shrinks tzcode’s attack surface, and is more efficient, ++ it fails to support Internet RFC 9636’s leap seconds. ++ ++ zic now can generate, and localtime.c can now use, TZif files that ++ hold up to 256 bytes of abbreviations, counting trailing NULs. ++ The previous limit was 50 bytes, and some tzdata TZif files were ++ already consuming 40 bytes. zic -v warns if it generates a file ++ that exceeds the old 50-byte limit. ++ ++ zic -L can now generate TZif files with more than 50 leap seconds. ++ This helps test TZif readers not limited to 50 leap seconds, as ++ tzcode’s localtime.c is; it has little immediate need for ++ practical timekeeping as there have been only 27 leap seconds and ++ possibly there will be no more, due to planned changes to UTC. ++ zic -v warns if its output exceeds the old 50-second limit. ++ ++ localtime.c no longer accesses the posixrules file generated by ++ zic -p. Hence for obsolete and nonconforming settings like ++ TZ="AST4ADT" it now typically falls back on US DST rules, rather ++ than attempting to override this fallback with the contents of the ++ posixrules file. This removes library support that was declared ++ obsolete in release 2019b, and fixes some undefined behavior. ++ (Undefined behavior reported by GitHub user Naveed8951.) ++ ++ The posix2time, posix2time_z, time2posix, and time2posix_z ++ functions now set errno=EOVERFLOW and return ((time_t) -1) if the ++ result is not representable. Formerly they had undefined behavior ++ that could in practice result in crashing, looping indefinitely, ++ or returning an incorrect result. As before, these functions are ++ defined only when localtime.c is compiled with the -DSTD_INSPIRED ++ option. ++ ++ Some other undefined behavior, triggered by TZif files containing ++ outlandish but conforming UT offsets or leap second corrections, ++ has also been fixed. (Some of these bugs reported by Naveed8951.) ++ ++ localtime.c no longer rejects TZif files that exactly fit in its ++ internal structures, fixing off-by-one typos introduced in 2014g. ++ ++ zic no longer generates a no-op transition when ++ simultaneous Rule and Zone changes cancel each other out. ++ This occurs in tzdata only in Asia/Tbilisi on 1997-03-30. ++ (Thanks to Renchunhui for a test case showing the bug.) ++ ++ zic no longer assumes you can fflush a read-only stream. ++ (Problem reported by Christos Zoulas.) ++ ++ zic no longer generates UT offsets equal to -2**31 and localtime.c ++ no longer accepts them, as they can cause trouble in both ++ localtime.c and its callers. RFC 9636 prohibits such offsets. ++ ++ zic -p now warns that the -p option is obsolete and likely ++ ineffective. ++ ++ + Release 2025c - 2025-12-10 14:42:37 -0800 + + Briefly: +@@ -69,6 +201,8 @@ + The new CFLAGS options -DHAVE_STRUCT_STAT_ST_CTIM=0 and + -DHAVE_STRUCT_TIMESPEC=0 port to non-POSIX.1-2008 platforms + that lack st_ctim and struct timespec, respectively. ++ On these platforms, the code falls back on st_ctime to ++ implement -DTZ_CHANGE_INTERVAL=N. + + tzset etc. now treat ' ' like '_' in time zone abbreviations, + just as they treat other invalid bytes. This continues the +@@ -89,7 +223,7 @@ + + The new CFLAGS option -TTHREAD_TM_MULTI causes localtime to return + a pointer to thread-specific memory, as FreeBSD does, instead of +- to the same memory in all threads. This supports unportable ++ to the same memory in all threads. This supports nonportable + programs that incorrectly use localtime instead of localtime_r. + This option affects gmtime and offtime similarly to localtime. + Because the corresponding storage is freed on thread exit, this +--- contrib/tzdata/backzone.orig ++++ contrib/tzdata/backzone +@@ -1757,13 +1757,12 @@ + # Midway + # + # From Mark Brader (2005-01-23): +-# [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies, +-# published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3] ++# [<https://www.timetableimages.com/ttimages/pa/pa36/pa36.pdf>] + # reproduced a Pan American Airways timetable from 1936, for their weekly + # "Orient Express" flights between San Francisco and Manila, and connecting + # flights to Chicago and the US East Coast. As it uses some time zone + # designations that I've never seen before:.... +-# Fri. 6:30A Lv. HONOLOLU (Pearl Harbor), H.I. H.L.T. Ar. 5:30P Sun. ++# Fri. 6:30A Lv. HONOLULU (Pearl Harbor), H.I. . H.L.T. Ar. 5:30P Sun. + # " 3:00P Ar. MIDWAY ISLAND . . . . . . . . . M.L.T. Lv. 6:00A " + # + Zone Pacific/Midway -11:49:28 - LMT 1901 +--- contrib/tzdata/etcetera.orig ++++ contrib/tzdata/etcetera +@@ -20,7 +20,8 @@ + # which load the "UTC" file to handle seconds properly. + Zone Etc/UTC 0 - UTC + +-# Functions like gmtime load the "GMT" file to handle leap seconds properly. ++# If leap second support is enabled, functions like gmtime ++# load the "GMT" file to handle leap seconds properly. + # Vanguard section, which works with most .zi parsers. + #Zone GMT 0 - GMT + # Rearguard section, for TZUpdater 2.3.2 and earlier. +--- contrib/tzdata/europe.orig ++++ contrib/tzdata/europe +@@ -1041,9 +1041,19 @@ + + # Greenland + # +-# From Paul Eggert (2004-10-31): ++# From Paul Eggert (2026-01-22): ++# During World War II, Greenland was effectively independent of Denmark and ++# observed daylight saving time. TIME, volume 37, page 23 (1941-04-21) ++# <https://time.com/archive/6770243/war-peace-greenlands-icy-mountains/> says, ++# "Penfield and West made their way to the U.S.'s most northerly consulate. ++# They were astonished to find that Greenlanders, with almost 24 hours of ++# sunlight a day during the summer, have daylight saving time." ++# As the details are unknown they are omitted from the data for now. ++# + # During World War II, Germany maintained secret manned weather stations in + # East Greenland and Franz Josef Land, but we don't know their time zones. ++# Also, they're likely out of scope for the database ++# as we lack resources to track every bit of military activity. + # My source for this is Wilhelm Dege's book mentioned under Svalbard. + # + # From Paul Eggert (2017-12-10): +@@ -1957,7 +1967,6 @@ + + # From Stepan Golosunov (2016-03-07): + # the act of the government of the Republic of Moldova Nr. 132 from 1990-05-04 +-# http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=2 + # ... says that since 1990-05-06 on the territory of the Moldavian SSR + # time would be calculated as the standard time of the second time belt + # plus one hour of the "summer" time. To implement that clocks would be +@@ -2012,9 +2021,61 @@ + # says the 2014-03-30 spring-forward transition was at 02:00 local time. + # Guess that since 1997 Moldova has switched one hour before the EU. + ++# From Heitor David Pinto (2026-02-22): ++# Soviet Moldovan resolution 132 of 1990 defined the summer time period from ++# the last Sunday in March at 2:00 to the last Sunday in September at 3:00, ++# matching the dates used in most of Europe at the time: ++# https://web.archive.org/web/20211107050832/http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=1 ++# ++# It seems that in 1996 Moldova changed the end date to October like most of ++# Europe, but kept the transitions at 2:00 and 3:00 rather than 1:00 UTC, ++# which would have been locally 3:00 and 4:00.... ++# ++# The notices in the Moldovan government website and broadcaster showed the ++# transitions at 2:00 and 3:00 until 2021: ++# 2015 https://old.gov.md/en/node/7304 ++# 2016 https://old.gov.md/en/node/12587 ++# 2017 https://old.gov.md/en/node/20654 ++# 2017 https://old.gov.md/en/content/moldova-upholds-winter-time-night-28-29-october ++# 2018 https://old.gov.md/en/content/moldova-switch-summer-time ++# 2018 https://old.gov.md/en/content/cabinet-ministers-informs-about-switch-winter-time-28-october ++# 2019 https://old.gov.md/en/content/moldova-switch-summer-time-31-march ++# 2019 https://old.gov.md/en/node/31122 ++# 2020 https://old.gov.md/en/node/32771 ++# 2020 https://old.gov.md/en/node/34497 ++# 2021 https://trm.md/ro/social/moldova-trece-in-aceasta-noapte-la-ora-de-vara ++# 2021 https://trm.md/en/social/republica-moldova-trece-la-ora-de-iarna1 ++# ++# However, since 2022, the notices showed the transitions at 3:00 and 4:00, ++# matching the EU rule at 1:00 UTC: ++# 2022 https://trm.md/en/social/in-acest-weekend-republica-moldova-trece-la-ora-de-vara ++# 2022 https://old.gov.md/en/content/moldova-switch-winter-time ++# 2023 https://moldova1.md/p/6587/ora-de-vara-2023-cum-schimbam-acele-ceasornicelor-si-cand-trecem-la-ora-de-vara ++# 2023 https://old.gov.md/en/node/46662 ++# 2024 https://moldova1.md/p/26535/republica-moldova-trece-la-ora-de-vara-in-acest-weekend ++# 2024 https://moldova1.md/p/37768/republica-moldova-trece-in-aceasta-noapte-la-ora-de-iarna ++# 2025 https://moldova1.md/p/46349/republica-moldova-trece-la-ora-de-vara-pe-30-martie-cum-ne-afecteaza-si-ce-recomanda-medicii ++# 2025 https://moldova1.md/p/60469/republica-moldova-trece-la-ora-de-iarna-ceasurile-se-dau-inapoi-cu-o-ora ++# ++# It seems that the changes to the end date and transition times were just ++# done in practice without formally changing the resolution. In late 2025, the ++# government said that the Soviet resolution was still in force, and proposed ++# a new resolution to replace it and formally establish the EU rule: ++# ... based on the notices, it seems that in practice Moldova already ++# uses the EU rule since 2022. This was also the year when Moldova applied to ++# join the EU. ++# ++# From Robert Bastian (2026-02-26): ++# This has been approved and published in the government gazette: ++# https://monitorul.gov.md/ro/monitorul/view/pdf/3234/part/2#page=27 ++# ++# From Paul Eggert (2026-02-24): ++# Also see Svetlana Rudenko, "Moldova abandons the 'Soviet era'", Logos Press, ++# 2026-02-21 <https://logos-pres.md/en/news/moldova-abandons-the-soviet-era/>. ++ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S +-Rule Moldova 1997 max - Oct lastSun 3:00 0 - ++Rule Moldova 1997 2021 - Mar lastSun 2:00 1:00 S ++Rule Moldova 1997 2021 - Oct lastSun 3:00 0 - + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Europe/Chisinau 1:55:20 - LMT 1880 +@@ -2027,7 +2088,8 @@ + 2:00 Russia EE%sT 1992 + 2:00 E-Eur EE%sT 1997 + # See Romania commentary for the guessed 1997 transition to EU rules. +- 2:00 Moldova EE%sT ++ 2:00 Moldova EE%sT 2022 ++ 2:00 EU EE%sT + + # Poland + +@@ -2413,7 +2475,7 @@ + # Nine O'clock <http://www.nineoclock.ro/POL/1778pol.html> + # (1998-10-23) reports that the switch occurred at + # 04:00 local time in fall 1998. For lack of better info, +-# assume that Romania and Moldova switched to EU rules in 1997, ++# assume that Romania switched to EU rules in 1997, + # the same year as Bulgaria. + # + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +--- contrib/tzdata/leap-seconds.list.orig ++++ contrib/tzdata/leap-seconds.list +@@ -60,15 +60,15 @@ + # + # The following line shows the last update of this file in NTP timestamp: + # +-#$ 3960835200 ++#$ 3976686858 + # + # 2) Expiration date of the file given on a semi-annual basis: last June or last December + # +-# File expires on 28 June 2026 ++# File expires on 28 December 2026 + # + # Expire date in NTP timestamp: + # +-#@ 3991593600 ++#@ 4007404800 + # + # + # LIST OF LEAP SECONDS +@@ -117,4 +117,4 @@ + # please see the readme file in the 'source' directory : + # https://hpiers.obspm.fr/iers/bul/bulc/ntp/sources/README + # +-#h 49db2447 571e5e1b 2f002a53 9c8da8e4 39b8e49e ++#h 2e101270 4e6749f8 2f1792b7 14a0c188 36bb19d6 +--- contrib/tzdata/leapseconds.orig ++++ contrib/tzdata/leapseconds +@@ -70,7 +70,7 @@ + # Any additional leap seconds will come after this. + # This Expires line is commented out for now, + # so that pre-2020a zic implementations do not reject this file. +-#Expires 2026 Jun 28 00:00:00 ++#Expires 2026 Dec 28 00:00:00 + + # Here are POSIX timestamps for the data in this file. + # "#updated" gives the last time the leap seconds data changed +@@ -79,8 +79,8 @@ + # "#expires" gives the first time this file might be wrong; + # if this file was derived from the IERS leap-seconds.list, + # this is typically a bit less than one year after "updated". +-#updated 1751846400 (2025-07-07 00:00:00 UTC) +-#expires 1782604800 (2026-06-28 00:00:00 UTC) ++#updated 1767698058 (2026-01-06 11:14:18 UTC) ++#expires 1798416000 (2026-12-28 00:00:00 UTC) + + # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) +-# File expires on 28 June 2026 ++# File expires on 28 December 2026 +--- contrib/tzdata/northamerica.orig ++++ contrib/tzdata/northamerica +@@ -1957,6 +1957,56 @@ + # https://searcharchives.vancouver.ca/daylight-saving-1918-starts-again-july-7-1941-start-d-s-sept-27-end-of-d-s-1941 + # We have no further details, so omit them for now. + ++# From Arthur David Olson (2026-03-02): ++# B. C. Gov News: “Adopting permanent daylight saving time: ‘Spring forward’ ++# on March 8 will be the last time change, ending twice-yearly clock changes.” ++# https://news.gov.bc.ca/releases/2026AG0013-000209 ++# ++# From Paul Eggert (2026-03-07): ++# The law says that 21 hours after the usual 2026-03-08 02:00 switch from ++# PST to PDT, the next day inaugurates the new standard time Pacific Time, ++# i.e., just one clock change but two name changes separated by 21 hours. ++# PT, the obvious abbreviation for Pacific Time, is one letter too short ++# to conform to TZDB’s (and POSIX’s) [-+[:alnum:]]{3,6} requirements. ++# I asked the BC government for advice, with no response. For now, do this: ++# 1. As a temporary hack, pretend that the BC law takes effect ++# not on 2026-03-09 at 00:00, but on 2026-11-01 at 02:00. ++# This pretense works around a limitation in CLDR v48.2 (2026-03-17), ++# which would otherwise say the interval uses “Pacific Standard Time”. ++# (Below, this temporary hack is marked “Temporary hack; see above.”) ++# Strictly speaking this hack is incorrect since the interval uses ++# standard time, but it does have the right UT offset and it ++# works around the CLDR limitation. We should be able to remove ++# the temporary hack after CLDR is fixed. ++# 2. After the BC law takes effect, model the time as MST sans DST. ++# We can change this later if another conforming non-numeric abbreviation ++# for Pacific Time becomes more popular. Possibilities include: ++# MST - the most compatible with existing software and practice, ++# and already used in parts of BC and in Yukon ++# PDT - almost as software-friendly, but confusing because it implies ++# it is DST and is paired with PST, whereas PT is standard time ++# PST - straightforward but even more confusing, ++# and will likely break much software that assumes PST is -08 ++# -07 - accurate and clear in itself, but makes BC look odd vs neighbors ++# CPT, CPST - for Canadian Pacific (Standard) Time, ++# by analogy with AEST in Australia ++# P-T - conforming approximation to “PT” ++# PT+ - like P-T but suggesting one-hour advance over PST ++ ++# From Chris Walton (2026-03-15): ++# The Regional District of East Kootenay is planning to move to year-round ++# Mountain Standard Time (MST) on November 1, 2026.... ++# https://www.rdek.bc.ca/news/entry/rdek_board_moves_to_transition_to_year_round_mountain_standard_time ++# (2026-03-17): ++# The final decision East Kootenay made a few days ago may turn out not to ++# be final after all. They are going to reopen the debate next month! ++# https://www.cbc.ca/news/canada/british-columbia/what-time-is-it-in-the-east-kootenay-debate-9.7132624 ++# From Paul Eggert (2026-03-17): ++# Mayor Steve Fairbairn of Elkford asked the question be called a second time, ++# saying, “Pardon the pun, but this is not a time-sensitive issue.” ++# For now, merely mention the potential change in these comments. ++# If it happens it would likely affect clocks starting 2027-03-14 at 02:00. ++ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S + Rule Vanc 1918 only - Apr 14 2:00 1:00 D + Rule Vanc 1918 only - Oct 27 2:00 0 S +@@ -1970,7 +2020,11 @@ + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Vancouver -8:12:28 - LMT 1884 + -8:00 Vanc P%sT 1987 +- -8:00 Canada P%sT ++ -8:00 Canada P%sT 2026 Mar 9 ++ # Temporary hack; see above. ++ -8:00 1:00 PDT 2026 Nov 1 02:00 ++ # End of temporary hack. ++ -7:00 - MST + Zone America/Dawson_Creek -8:00:56 - LMT 1884 + -8:00 Canada P%sT 1947 + -8:00 Vanc P%sT 1972 Aug 30 2:00 +--- contrib/tzdata/theory.html.orig ++++ contrib/tzdata/theory.html +@@ -3,14 +3,16 @@ + <head> + <title>Theory and pragmatics of the tz code and data</title> + <meta charset="UTF-8"> ++ <meta name="viewport" content="width=device-width, initial-scale=1"> + <style> +- pre {margin-left: 2em; white-space: pre-wrap;} ++ dd {margin-left: 1.3rem;} ++ pre {margin-left: 1.3rem; overflow: auto;} ++ ul {padding-left: 1.3rem;} + </style> + </head> + + <body> + <h1>Theory and pragmatics of the <code><abbr>tz</abbr></code> code and data</h1> +- <h3>Outline</h3> + <nav> + <ul> + <li><a href="#scope">Scope of the <code><abbr>tz</abbr></code> +@@ -648,14 +650,14 @@ + should be observed. + In her 2015 book + <cite><a +- href="https://www.hup.harvard.edu/catalog.php?isbn=9780674286146">The ++ href="https://www.hup.harvard.edu/books/9780674286146">The + Global Transformation of Time, 1870–1950</a></cite>, + Vanessa Ogle writes + “Outside of Europe and North America there was no system of time + zones at all, often not even a stable landscape of mean times, + prior to the middle decades of the twentieth century”. + See: Timothy Shenk, <a +-href="https://www.dissentmagazine.org/blog/booked-a-global-history-of-time-vanessa-ogle">Booked: ++href="https://dissentmagazine.org/blog/booked-a-global-history-of-time-vanessa-ogle/">Booked: + A Global History of Time</a>. <cite>Dissent</cite> 2015-12-17. + </li> + <li> +@@ -789,7 +791,7 @@ + calendar with 24-hour days. These divergences range from + relatively minor, such as Japanese bars giving times like 24:30 for the + wee hours of the morning, to more-significant differences such as <a +- href="https://theworld.org/stories/2015-01-30/if-you-have-meeting-ethiopia-you-better-double-check-time">the ++ href="https://theworld.org/stories/2015/01/30/ethiopian-time">the + east African practice of starting the day at dawn</a>, renumbering + the Western 06:00 to be 12:00. These practices are largely outside + the scope of the <code><abbr>tz</abbr></code> code and data, which +@@ -1126,7 +1128,7 @@ + the name of a file from which time-related information is read. + The file’s format is <dfn><abbr>TZif</abbr></dfn>, + a timezone information format that contains binary data; see +- <a href="https://www.rfc-editor.org/rfc/9636">Internet ++ <a href="https://www.rfc-editor.org/rfc/rfc9636">Internet + <abbr>RFC</abbr> 9636</a>. + The daylight saving time rules to be used for a + particular timezone are encoded in the +@@ -1438,7 +1440,7 @@ + extended the time zone database further into the past. + An excellent resource in this area is Edward M. Reingold + and Nachum Dershowitz, <cite><a +-href="https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition">Calendrical ++href="https://www.cambridge.org/fr/universitypress/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition">Calendrical + Calculations: The Ultimate Edition</a></cite>, Cambridge University Press (2018). + Other information and sources are given in the file "<code>calendars</code>" + in the <code><abbr>tz</abbr></code> distribution. +@@ -1450,13 +1452,13 @@ + <h2 id="planets">Time and time zones off Earth</h2> + <p> + The European Space Agency is <a +-href="https://www.esa.int/Applications/Navigation/Telling_time_on_the_Moon">considering</a> ++href="https://www.esa.int/Applications/Satellite_navigation/Telling_time_on_the_Moon">considering</a> + the establishment of a reference timescale for the Moon, which has + days roughly equivalent to 29.5 Earth days, and where relativistic + effects cause clocks to tick slightly faster than on Earth. + Also, <abbr title="National Aeronautics and Space Administration">NASA</abbr> + has been <a +-href="https://www.whitehouse.gov/wp-content/uploads/2024/04/Celestial-Time-Standardization-Policy.pdf">ordered</a> ++href="https://bidenwhitehouse.archives.gov/wp-content/uploads/2024/04/Celestial-Time-Standardization-Policy.pdf">ordered</a> + to consider the establishment of Coordinated Lunar Time (<abbr>LTC</abbr>). + It is not yet known whether the US and European efforts will result in + multiple timescales on the Moon. +@@ -1576,7 +1578,7 @@ + </li> + <li> + Matt Williams, +- “<a href="https://www.universetoday.com/37481/days-of-the-planets/">How ++ “<a href="https://www.universetoday.com/articles/days-of-the-planets">How + long is a day on the other planets of the solar system?</a>” + (2016-01-20). + </li> +--- contrib/tzdata/version.orig ++++ contrib/tzdata/version +@@ -1 +1 @@ +-2025c ++2026b +--- contrib/tzdata/zone.tab.orig ++++ contrib/tzdata/zone.tab +@@ -124,12 +124,12 @@ + CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) + CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) + CA +682059-1334300 America/Inuvik Mountain - NT (west) ++CA +4916-12307 America/Vancouver MST - BC (most areas) + CA +4906-11631 America/Creston MST - BC (Creston) + CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) + CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) + CA +6043-13503 America/Whitehorse MST - Yukon (east) + CA +6404-13925 America/Dawson MST - Yukon (west) +-CA +4916-12307 America/Vancouver Pacific - BC (most areas) + CC -1210+09655 Indian/Cocos + CD -0418+01518 Africa/Kinshasa Dem. Rep. of Congo (west) + CD -1140+02728 Africa/Lubumbashi Dem. Rep. of Congo (east) +--- contrib/tzdata/zone1970.tab.orig ++++ contrib/tzdata/zone1970.tab +@@ -116,11 +116,11 @@ + CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) + CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) + CA +682059-1334300 America/Inuvik Mountain - NT (west) ++CA +4916-12307 America/Vancouver MST - BC (most areas) + CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) + CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) + CA +6043-13503 America/Whitehorse MST - Yukon (east) + CA +6404-13925 America/Dawson MST - Yukon (west) +-CA +4916-12307 America/Vancouver Pacific - BC (most areas) + CH,DE,LI +4723+00832 Europe/Zurich Büsingen + CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan + CK -2114-15946 Pacific/Rarotonga +--- contrib/tzdata/zonenow.tab.orig ++++ contrib/tzdata/zonenow.tab +@@ -58,6 +58,9 @@ + # -08/-07 - PST/PDT (North America DST) + XX +340308-1181434 America/Los_Angeles Pacific (PST/PDT) - US & Canada; Mexico near US border + # ++# -08/-07 - PST/PDT (North America DST) until 2026-11-01 02:00; then MST ++XX +4916-12307 America/Vancouver MST - BC (most areas) ++# + # -07 - MST + XX +332654-1120424 America/Phoenix Mountain Standard (MST) - Arizona; western Mexico; Yukon + # +@@ -166,9 +169,6 @@ + # +02/+03 - EET/EEST (Lebanon DST) + XX +3353+03530 Asia/Beirut Lebanon + # +-# +02/+03 - EET/EEST (Moldova DST) +-XX +4700+02850 Europe/Chisinau Moldova +-# + # +02/+03 - EET/EEST (Palestine DST) + XX +3130+03428 Asia/Gaza Palestine + # diff --git a/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch.asc b/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch.asc new file mode 100644 index 0000000000..ff2ea80a52 --- /dev/null +++ b/website/static/security/patches/EN-26:09/tzdata-2026b-144.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRQbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvkPcP/3HirKAYpc85/+W6HDSW +9YqLpeBk70S7Tx4ZsvVkbBCFLQWVSjugbVbyztrxNzzIlEB6f9Lz415iooIkevPd +a43NTgWC0pKJAAFgiA2yHeOixz1yqse4oQRuqCOMaOP80PRS3T+d9KP+65rADfYu +jQZjPKUrtyTEKxwY4jAlhUxsqn0MDeIcN/n6JU3C45YCRsJqcjuO3+d5BhZibAeL +ERoBq1vg5XoiP0sNZ74Ci/V45Pvnipz9CQNLOOQy0/X97RYtS+csCassYOzqCfsb +EO94m8h2F693hKMfX/y7IABC9aHU57EvQQElY6ZygNjfHc5hkwLSb/XZzo3d5SFX +s8FKBg5afeWAInWV3TfZskaMEJUTOb5qddZb7sVDhp5JfgGOstOAFyvWpr3OBhZX +HapsjgslX3gbnPfvAgJwJK/Fzbkb6eTwJz0BRbZVIRqmACb3ylvH55ZGESHOILAG +Mv4bW12focI01WyUJuDmV5YxPif4jTFGgPqlmgjoMkW0WBx5sxfvVMNkfdSJ2Pic +hHtle0BlFzbpKHJnu15D/ZpmHHjcCQVkGB0/ygaqwHmxkMcOJZgtQWn+I1HKdtwu +GHtvcU9nuWd+gnREYsvqWxo19gZql8/CKZtHaGlIYUpj36hFIb34ORM7iWs+aQD9 +BVdiWZTnnzrgmFjfAOtptlAV +=ACp+ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:09/tzdata-2026b.patch b/website/static/security/patches/EN-26:09/tzdata-2026b.patch new file mode 100644 index 0000000000..7d25008469 --- /dev/null +++ b/website/static/security/patches/EN-26:09/tzdata-2026b.patch @@ -0,0 +1,3015 @@ +--- contrib/tzdata/CONTRIBUTING.orig ++++ contrib/tzdata/CONTRIBUTING +@@ -10,26 +10,27 @@ + 1970, and undoubtedly errors remain in the code and data. Feel + free to fill gaps or fix mistakes, and please email improvements + to <tz@iana.org> for use in the future. In your email, please give +-reliable sources that reviewers can check. ++reliable sources that reviewers can check. The mailing list and its ++archives are public, so please do not send confidential information. + + ## Contributing technical changes + + To email small changes, please run a POSIX shell command like +-'diff -u old/europe new/europe >myfix.patch', and attach +-'myfix.patch' to the email. ++‘diff -u old/europe new/europe >myfix.patch’, and attach ++‘myfix.patch’ to the email. + + For more-elaborate or possibly controversial changes, + such as renaming, adding or removing zones, please read +-"Theory and pragmatics of the tz code and data" ++“Theory and pragmatics of the tz code and data” + <https://www.iana.org/time-zones/repository/theory.html>. + It is also good to browse the mailing list archives + <https://lists.iana.org/hyperkitty/list/tz@iana.org/> + for examples of patches that tend to work well. + Changes should contain commentary citing reliable sources. +-Citations should use "https:" URLs if available. ++Citations should use ‘https:’ URLs if available. + + For changes that fix sensitive security-related bugs, please see the +-distribution's 'SECURITY' file. ++distribution’s SECURITY file. + + Please submit changes against either the latest release + <https://www.iana.org/time-zones> or the main branch of the development +@@ -54,11 +55,11 @@ + + git checkout -b mybranch + +- * Sleuth by using 'git blame'. For example, when fixing data for +- Africa/Sao_Tome, if the command 'git blame africa' outputs a line +- '2951fa3b (Paul Eggert 2018-01-08 09:03:13 -0800 1068) Zone +- Africa/Sao_Tome 0:26:56 - LMT 1884', commit 2951fa3b should +- provide some justification for the 'Zone Africa/Sao_Tome' line. ++ * Sleuth by using ‘git blame’. For example, when fixing data for ++ Africa/Sao_Tome, if the command ‘git blame africa’ outputs a line ++ ‘2951fa3b (Paul Eggert 2018-01-08 09:03:13 -0800 1068) Zone ++ Africa/Sao_Tome 0:26:56 - LMT 1884’, commit 2951fa3b should ++ provide some justification for the ‘Zone Africa/Sao_Tome’ line. + + * Edit source files. Include commentary that justifies the + changes by citing reliable sources. +@@ -69,28 +70,31 @@ + ./zdump -v America/Los_Angeles + + Although builds assume only basic POSIX, they use extra features +- if available. 'make check' accesses validator.w3.org unless you +- lack 'curl' or use 'make CURL=:'. If you have the latest GCC, +- "make CFLAGS='$(GCC_DEBUG_FLAGS)'" does extra checking. ++ if available. ‘make check’ accesses validator.w3.org unless you ++ lack ‘curl’ or use ‘make CURL=:’. If you have the latest GCC, ++ ‘make CFLAGS='$(GCC_DEBUG_FLAGS)'’ does extra checking. + + * For each separable change, commit it in the new branch, e.g.: + + git add northamerica + git commit + +- See recent 'git log' output for the commit-message style. ++ See recent ‘git log’ output for the commit-message style. + + * Create patch files 0001-..., 0002-..., ... + + git format-patch main + ++ * Check that the patch files and your email setup contain only ++ information that you want to make public. ++ + * After reviewing the patch files, send the patches to <tz@iana.org> + for others to review. + + git send-email main + + For an archived example of such an email, see +- "[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913" ++ “[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913” + <https://mm.icann.org/pipermail/tz/2018-February/026122.html>. + + * Start anew by getting current with the main branch again +--- contrib/tzdata/Makefile.orig ++++ contrib/tzdata/Makefile +@@ -3,17 +3,30 @@ + # 2009-05-17 by Arthur David Olson. + # Request POSIX conformance; this must be the first non-comment line. + .POSIX: ++# By default, builds of code and data assume POSIX.1-2001 or later; ++# this assumption can be relaxed by tailoring the build as described below. + # On older platforms you may need to scrounge for POSIX conformance. + # For example, on Solaris 10 (2005) with Sun Studio 12 aka Sun C 5.9 (2007), + # use 'PATH=/usr/xpg4/bin:$PATH make CC=c99'. ++# Reproducible builds of distribution tarballs also need a copy of the ++# Git repository, and assume the behavior of the following programs ++# (or later versions): ++# Git 2.7.0 (2016) ++# GNU Coreutils 6.3 (2006) ++# GNU Tar 1.14 (2004) ++# GnuPG 1.4 (2004) ++# Although tzdb does not come with a software bill of materials, ++# you should be able to construct one based on the above information, ++# your platform, and the way you use this Makefile. + + # To affect how this Makefile works, you can run a shell script like this: + # + # #!/bin/sh +-# make CC='gcc -std=gnu23' "$@" ++# make CFLAGS='-O2 -DHAVE_GETTEXT=0' "$@" + # +-# This example script is appropriate for a circa 2024 GNU/Linux system +-# where a non-default setting enables this package's optional use of C23. ++# This example script is appropriate for a GNU/Linux system ++# which needs more optimization than default, and which does not want ++# gettext's internationalization of diagnostics. + # + # Alternatively, you can simply edit this Makefile to tailor the following + # macro definitions. +@@ -53,28 +66,6 @@ + + LOCALTIME= Factory + +-# The POSIXRULES macro controls interpretation of POSIX-like TZ +-# settings like TZ='EET-2EEST' that lack DST transition rules. +-# If POSIXRULES is '-', no template is installed; this is the default. +-# Any other value for POSIXRULES is obsolete and should not be relied on, as: +-# * It does not work correctly in popular implementations such as GNU/Linux. +-# * It does not work even in tzcode, except for historical timestamps +-# that precede the last explicit transition in the POSIXRULES file. +-# Hence it typically does not work for current and future timestamps. +-# If, despite the above, you want a template for handling these settings, +-# you can change the line below (after finding the timezone you want in the +-# one of the $(TDATA) source files, or adding it to a source file). +-# Alternatively, if you discover you've got the wrong timezone, you can just +-# 'zic -p -' to remove it, or 'zic -p rightzone' to change it. +-# Use the command +-# make zonenames +-# to get a list of the values you can use for POSIXRULES. +- +-POSIXRULES= - +- +-# Also see TZDEFRULESTRING below, which takes effect only +-# if POSIXRULES is '-' or if the template file cannot be accessed. +- + + # Installation locations. + # +@@ -150,13 +141,14 @@ + # below. If you want both sets of data available, with leap seconds counted + # normally, use + # REDO= right_posix +-# below. POSIX mandates that leap seconds not be counted; for compatibility +-# with it, use "posix_only" or "posix_right". Use POSIX time on systems with ++# below. POSIX mandates that leap seconds not be counted, and a ++# nonnegative TZ_CHANGE_INTERVAL also assumes this, so to be compatible with ++# these, use "posix_only" or "posix_right". Use POSIX time on systems with + # leap smearing; this can work better than unsmeared "right" time with + # applications that are not leap second aware, and is closer to unsmeared + # "right" time than unsmeared POSIX time is (e.g., 0.5 vs 1.0 s max error). + +-REDO= posix_right ++REDO= posix_only + + # Whether to put an "Expires" line in the leapseconds file. + # Use EXPIRES_LINE=1 to put the line in, 0 to omit it. +@@ -206,6 +198,12 @@ + + UTF8_LOCALE= en_US.utf8 + ++# Extra flags for producing man page files like tzfile.5.txt. ++# These flags are used only if groff (or mandoc) is present. ++# Each option should begin with "-" and should lack shell metacharacters. ++# Plausible options include -Tascii and -Tutf8. ++MANFLAGS= -Tutf8 ++ + # Non-default libraries needed to link. + # On some hosts, this should have -lintl unless CFLAGS has -DHAVE_GETTEXT=0. + LDLIBS= +@@ -219,14 +217,19 @@ + # -DEPOCH_OFFSET=N if the 'time' function returns a value N greater + # than what POSIX specifies, assuming local time is UT. + # For example, N is 252460800 on AmigaOS. ++# -DFREE_PRESERVES_ERRNO=[01] if the 'free' function munges or preserves errno ++# (default is guessed) + # -DHAVE_DECL_ASCTIME_R=0 if <time.h> does not declare asctime_r + # on POSIX platforms predating POSIX.1-2024 + # -DHAVE_DECL_ENVIRON if <unistd.h> declares 'environ' + # -DHAVE_DECL_TIMEGM=0 if <time.h> does not declare timegm + # -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows) ++# -DHAVE_FCHMOD=0 if your system lacks the fchmod function + # -DHAVE__GENERIC=0 if _Generic does not work* ++# -DHAVE_GETEUID=0 if gete?[ug]id do not work + # -DHAVE_GETRANDOM if getrandom works (e.g., GNU/Linux), + # -DHAVE_GETRANDOM=0 to avoid using getrandom ++# -DHAVE_GETRESUID=0 if getres[ug]id do not work + # -DHAVE_GETTEXT if gettext works (e.g., GNU/Linux, FreeBSD, Solaris), + # where LDLIBS also needs to contain -lintl on some hosts; + # -DHAVE_GETTEXT=0 to avoid using gettext +@@ -234,28 +237,46 @@ + # ctime_r and asctime_r incompatibly with POSIX.1-2017 and earlier + # (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined). + # -DHAVE_INTTYPES_H=0 if <inttypes.h> does not work*+ ++# -DHAVE_ISSETUGID=1 if issetugid works, 0 otherwise (default is guessed) ++# If 0, you may also use -DHAVE_SYS_AUXV_H=1 if <sys/auxv.h> works, ++# 0 otherwise (default is guessed). + # -DHAVE_LINK=0 if your system lacks a link function + # -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function + # -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz + # localtime_rz can make zdump significantly faster, but is nonstandard. + # -DHAVE_MALLOC_ERRNO=0 if malloc etc. do not set errno on failure. ++# -DHAVE_MEMPCPY=1 if your system has mempcpy, 0 if not (default is guessed) + # -DHAVE_POSIX_DECLS=0 if your system's include files do not declare +-# functions like 'link' or variables like 'tzname' required by POSIX ++# variables like 'tzname' required by POSIX ++# -DHAVE_PWD_H=0 if your system lacks pwd.h, grp.h and corresponding functions ++# If 0, you may also need -Dgid_t=G -Duid_t=U ++# to define gid_t and uid_t to be types G and U. + # -DHAVE_SETENV=0 if your system lacks the setenv function ++# -DHAVE_SETMODE=[01] if your system lacks or has the setmode and getmode ++# functions (default is guessed) + # -DHAVE_SNPRINTF=0 if your system lacks the snprintf function+ + # -DHAVE_STDCKDINT_H=0 if neither <stdckdint.h> nor substitutes like + # __builtin_add_overflow work* + # -DHAVE_STDINT_H=0 if <stdint.h> does not work*+ + # -DHAVE_STRFTIME_L if <time.h> declares locale_t and strftime_l + # -DHAVE_STRDUP=0 if your system lacks the strdup function ++# -DHAVE_STRNLEN=0 if your system lacks the strnlen function+ + # -DHAVE_STRTOLL=0 if your system lacks the strtoll function+ ++# -DHAVE_STRUCT_STAT_ST_CTIM=0 if struct stat lacks a status-change member ++# of type struct timespec, so code should use st_ctime instead; ++# but if the status-change member name is st_ctimespec, ++# use -Dst_ctim=st_ctimespec instead (default is guessed)+ ++# -DHAVE_STRUCT_TIMESPEC=0 if your system lacks struct timespec+ + # -DHAVE_SYMLINK=0 if your system lacks the symlink function + # -DHAVE_SYS_STAT_H=0 if <sys/stat.h> does not work* ++# If 0, you may also need -Dmode_t=M to define mode_t to be type M. + # -DHAVE_TZSET=0 if your system lacks a tzset function + # -DHAVE_UNISTD_H=0 if <unistd.h> does not work* + # -DHAVE_UTMPX_H=0 if <utmpx.h> does not work* + # -Dlocale_t=XXX if your system uses XXX instead of locale_t + # -DMKTIME_MIGHT_OVERFLOW if mktime might fail due to time_t overflow ++# -DOPENAT_TZDIR if tzset should use openat on TZDIR then a relative open. ++# See localtime.c for details. + # -DPORT_TO_C89 if tzcode should also run on mostly-C89 platforms+ + # Typically it is better to use a later standard. For example, + # with GCC 4.9.4 (2016), prefer '-std=gnu11' to '-DPORT_TO_C89'. +@@ -274,15 +295,46 @@ + # -DTHREAD_SAFE to make localtime.c thread-safe, as POSIX requires; + # not needed by the main-program tz code, which is single-threaded. + # Append other compiler flags as needed, e.g., -pthread on GNU/Linux. ++# The following options can also be used: ++# -DTHREAD_PREFER_SINGLE to prefer speed in single-threaded apps, ++# at some cost in CPU time and energy in multi-threaded apps. ++# The following options can also be used: ++# -DHAVE___ISTHREADED=1 if there is an extern int __isthreaded ++# variable, 0 otherwise (default is guessed) ++# -DHAVE_SYS_SINGLE_THREADED_H=0 if <sys/single_threaded.h> works, ++# 0 otherwise (default is guessed) ++# -DTHREAD_RWLOCK to use read-write locks instead of mutexes. ++# This can improve parallelism and thus save real time ++# if many threads call tzcode functions simultaneously. ++# It also costs CPU time and thus energy. ++# -DTHREAD_TM_MULTI to have gmtime, localtime, and offtime ++# return different struct tm * addresses in different threads. ++# This supports nonportable programs that call ++# gmtime/localtime/offtime when they should call ++# gmtime_r/localtime_r/offtime_r to avoid races. ++# Because the corresponding storage is freed on thread exit, ++# this option is incompatible with POSIX.1-2024 and earlier. ++# It also costs CPU time and memory. + # -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t + # This is intended for internal use only; it mangles external names. ++# -DTZ_CHANGE_INTERVAL=N if functions depending on TZ should check ++# no more often than every N seconds for TZif file changes. ++# If N is negative (the default), no such checking is done. ++# This option is intended for platforms that want localtime etc. ++# to respond to changes to a file selected by TZ, including to ++# TZDEFAULT (normally /etc/localtime) if TZ is unset. ++# On these platforms, REDO should be "posix_only" or "posix_right". ++# This option does not affect tzalloc-allocated objects. + # -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" + # -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; + # the default is system-supplied, typically "/usr/lib/locale" ++# -DTZ_RUNTIME_LEAPS=0 to disable runtime support for leap seconds. ++# This conforms to POSIX, shrinks tzcode's attack surface, ++# and is more efficient. However, it fails to support Internet ++# RFC 9636's leap seconds. + # -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified +-# DST transitions for proleptic format TZ strings lacking them, +-# in the usual case where POSIXRULES is '-'. If not specified, +-# TZDEFRULESTRING defaults to US rules for future DST transitions. ++# DST transitions for proleptic format TZ strings lacking them. ++# If not specified, it defaults to US rules for future DST transitions. + # This mishandles some past timestamps, as US DST rules have changed. + # It also mishandles settings like TZ='EET-2EEST' for eastern Europe, + # as Europe and US DST rules differ. +@@ -314,7 +366,7 @@ + # Select instrumentation via "make GCC_INSTRUMENT='whatever'". + GCC_INSTRUMENT = \ + -fsanitize=undefined -fsanitize-address-use-after-scope \ +- -fsanitize-undefined-trap-on-error -fstack-protector ++ -fsanitize-trap=all -fstack-protector + # Omit -fanalyzer from GCC_DEBUG_FLAGS, as it makes GCC too slow. + GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 \ + $(GCC_INSTRUMENT) \ +@@ -332,12 +384,13 @@ + -Wold-style-definition -Woverlength-strings -Wpointer-arith \ + -Wshadow -Wshift-overflow=2 -Wstrict-overflow \ + -Wstrict-prototypes -Wstringop-overflow=4 \ +- -Wstringop-truncation -Wsuggest-attribute=cold \ ++ -Wsuggest-attribute=cold \ + -Wsuggest-attribute=const -Wsuggest-attribute=format \ + -Wsuggest-attribute=malloc \ + -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure \ + -Wtrampolines -Wundef -Wunused-macros -Wuse-after-free=3 \ + -Wvariadic-macros -Wvla -Wwrite-strings \ ++ -Wzero-as-null-pointer-constant \ + -Wno-format-nonliteral -Wno-sign-compare -Wno-type-limits + # + # If your system has a "GMT offset" field in its "struct tm"s +@@ -393,7 +446,9 @@ + # functions to be added to the time conversion library. + # "offtime" is like "gmtime" except that it accepts a second (long) argument + # that gives an offset to add to the time_t when converting it. +-# I.e., "offtime" is like calling "localtime_rz" with a fixed-offset zone. ++# "offtime_r" is to "offtime" what "gmtime_r" is to "gmtime". ++# I.e., "offtime" and "offtime_r" are like calling "localtime_rz" ++# with a fixed-offset zone. + # "timelocal" is nearly equivalent to "mktime". + # "timeoff" is like "timegm" except that it accepts a second (long) argument + # that gives an offset to use when converting to a time_t. +@@ -451,6 +506,11 @@ + https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list + # The file is generated by the IERS Earth Orientation Centre, in Paris. + leaplist_TZ = Europe/Paris ++# ++# To fetch leap-seconds.list from NIST via a less-secure protocol ++# and with less-volatile metadata, use these settings: ++#leaplist_URI = ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list ++#leaplist_TZ = America/Denver + + # The zic command and its arguments. + +@@ -510,13 +570,10 @@ + SAFE_CHARSET= $(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3) + SAFE_CHAR= '[]'$(SAFE_CHARSET)'-]' + +-# These non-alphabetic, non-ASCII printable characters are Latin-1, +-# and so are likely displayable even in editors like XEmacs 21 +-# that have limited display capabilities. +-UNUSUAL_OK_LATIN_1 = ¡¢£¤¥¦§¨©«¬®¯°±²³´¶·¸¹»¼½¾¿×÷ +-# Non-ASCII non-letters that OK_CHAR allows, as these characters are +-# useful in commentary. +-UNUSUAL_OK_CHARSET= $(UNUSUAL_OK_LATIN_1) ++# These non-alphabetic, non-ASCII printable characters are ++# used in commentary or in generated *.txt files ++# and are not likely to cause confusion. ++UNUSUAL_OK_CHARSET= §«°±»½¾×–‘’“”•→−≤★⟨⟩⯪ + + # Put this in a bracket expression to match spaces. + s = [:space:] +@@ -525,9 +582,6 @@ + # This is the same as SAFE_CHAR, except that UNUSUAL_OK_CHARSET and + # multibyte letters are also allowed so that commentary can contain a + # few safe symbols and people's names and can quote non-English sources. +-# Other non-letters are limited to ASCII renderings for the +-# convenience of maintainers using XEmacs 21.5.34, which by default +-# mishandles Unicode characters U+0100 and greater. + OK_CHAR= '[][:alpha:]$(UNUSUAL_OK_CHARSET)'$(SAFE_CHARSET)'-]' + + # SAFE_LINE matches a line of safe characters. +@@ -654,7 +708,6 @@ + '$(DESTDIR)$(MANDIR)/man3' '$(DESTDIR)$(MANDIR)/man5' \ + '$(DESTDIR)$(MANDIR)/man8' + $(ZIC_INSTALL) -l $(LOCALTIME) \ +- -p $(POSIXRULES) \ + -t '$(DESTDIR)$(TZDEFAULT)' + cp -f $(TABDATA) '$(DESTDIR)$(TZDIR)/.' + cp tzselect '$(DESTDIR)$(BINDIR)/.' +@@ -874,9 +927,9 @@ + character-set.ck: $(ENCHILADA) + $(UTF8_LOCALE_MISSING) || { \ + sharp='#' && \ +- ! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \ +- $(MISC) $(SOURCES) $(WEB_PAGES) \ +- CONTRIBUTING LICENSE README SECURITY \ ++ ! grep -Env $(SAFE_LINE) $(MANS) date.1 \ ++ $(MISC) $(SOURCES) \ ++ LICENSE \ + version tzdata.zi && \ + ! grep -Env $(SAFE_LINE)'|^UNUSUAL_OK_'$(OK_CHAR)'*$$' \ + Makefile && \ +@@ -888,11 +941,9 @@ + + white-space.ck: $(ENCHILADA) + $(UTF8_LOCALE_MISSING) || { \ +- enchilada='$(ENCHILADA)' && \ + patfmt=' \t|[\f\r\v]' && pat=$$(printf "$$patfmt\\n") && \ + ! grep -En "$$pat|[$s]\$$" \ +- $${enchilada%leap-seconds.list*} \ +- $${enchilada#*leap-seconds.list}; \ ++ $(ENCHILADA:leap-seconds.list=); \ + } + touch $@ + +@@ -959,8 +1010,10 @@ + ./zdump -i -t 0,$$future \ + $$(find "$$PWD/$@d" -name Etc -prune \ + -o -type f ! -name '*.tab' -print) \ +- >$@d/zdump-1970.tab ++ >$@d/zdump-1970.tab && \ + $(AWK) \ ++ -v now=$$now \ ++ -v now_out=$@.out \ + -v zdump_table=$@d/zdump-now.tab \ + -f checknow.awk zonenow.tab + $(AWK) \ +@@ -970,7 +1023,8 @@ + -v zdump_table=$@d/zdump-1970.tab \ + -f checknow.awk + rm -fr $@d +- touch $@ ++ touch $@.out ++ mv $@.out $@ + + tables.ck: checktab.awk $(YDATA) backward zone.tab zone1970.tab + for tab in $(ZONETABLES); do \ +@@ -1031,7 +1085,7 @@ + + clean_misc: + rm -fr *.ckd *.dir +- rm -f *.ck *.core *.o *.out core core.* \ ++ rm -f *.ck *.core *.o *.out *.t core core.* \ + date tzdir.h tzselect version.h zdump zic libtz.a + clean: clean_misc + rm -fr tzdb-*/ +@@ -1059,7 +1113,7 @@ + zic.8.txt: zic.8 + + $(MANTXTS): workman.sh +- LC_ALL=C sh workman.sh $(@:.txt=) >$@.out ++ LC_ALL=C sh workman.sh $(MANFLAGS) $(@:.txt=) >$@.out + mv $@.out $@ + + # Set file timestamps deterministically if possible, +@@ -1108,7 +1162,7 @@ + if git diff --quiet HEAD $$file; then \ + time=$$(TZ=UTC0 git log -1 \ + --format='tformat:%cd' \ +- --date='format:%Y-%m-%dT%H:%M:%SZ' \ ++ --date='format-local:%Y-%m-%dT%H:%M:%SZ' \ + $$file) && \ + echo "+ touch -md $$time $$file" && \ + touch -md $$time $$file; \ +@@ -1207,12 +1261,12 @@ + touch $@ + + TRADITIONAL_ASC = \ +- tzcode$(VERSION).tar.gz.asc \ +- tzdata$(VERSION).tar.gz.asc ++ tzcode$(VERSION).tar.gz.asc.t \ ++ tzdata$(VERSION).tar.gz.asc.t + REARGUARD_ASC = \ +- tzdata$(VERSION)-rearguard.tar.gz.asc ++ tzdata$(VERSION)-rearguard.tar.gz.asc.t + ALL_ASC = $(TRADITIONAL_ASC) $(REARGUARD_ASC) \ +- tzdb-$(VERSION).tar.lz.asc ++ tzdb-$(VERSION).tar.lz.asc.t + + tarballs rearguard_tarballs tailored_tarballs traditional_tarballs \ + signatures rearguard_signatures traditional_signatures: \ +@@ -1224,29 +1278,31 @@ + # other means. Ordinarily these rules are used only by the above + # non-_version rules, which set VERSION on the 'make' command line. + tarballs_version: traditional_tarballs_version rearguard_tarballs_version \ +- tzdb-$(VERSION).tar.lz ++ tzdb-$(VERSION).tar.lz.t + rearguard_tarballs_version: \ +- tzdata$(VERSION)-rearguard.tar.gz ++ tzdata$(VERSION)-rearguard.tar.gz.t + traditional_tarballs_version: \ +- tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz ++ tzcode$(VERSION).tar.gz.t tzdata$(VERSION).tar.gz.t + tailored_tarballs_version: \ +- tzdata$(VERSION)-tailored.tar.gz ++ tzdata$(VERSION)-tailored.tar.gz.t + signatures_version: $(ALL_ASC) + rearguard_signatures_version: $(REARGUARD_ASC) + traditional_signatures_version: $(TRADITIONAL_ASC) + +-tzcode$(VERSION).tar.gz: set-timestamps.out ++tzcode$(VERSION).tar.gz.t: set-timestamps.out + $(SETUP_TAR) && \ + $$TAR -cf - \ + $(COMMON) $(DOCS) $(SOURCES) | \ +- gzip $(GZIPFLAGS) >$@.out +- mv $@.out $@ ++ gzip $(GZIPFLAGS) >$(@:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) $(COMMON) $(DOCS) $(SOURCES) ++ touch $@ + +-tzdata$(VERSION).tar.gz: set-timestamps.out ++tzdata$(VERSION).tar.gz.t: set-timestamps.out + $(SETUP_TAR) && \ + $$TAR -cf - $(TZDATA_DIST) | \ +- gzip $(GZIPFLAGS) >$@.out +- mv $@.out $@ ++ gzip $(GZIPFLAGS) >$(@:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) $(TZDATA_DIST) ++ touch $@ + + # Create empty files with a reproducible timestamp. + CREATE_EMPTY = TZ=UTC0 touch -mt 202010122253.00 +@@ -1255,7 +1311,7 @@ + # for backwards compatibility with tz releases 2018e through 2022a. + # They should go away eventually. To build rearguard tarballs you + # can instead use 'make DATAFORM=rearguard tailored_tarballs'. +-tzdata$(VERSION)-rearguard.tar.gz: rearguard.zi set-timestamps.out ++tzdata$(VERSION)-rearguard.tar.gz.t: rearguard.zi set-timestamps.out + rm -fr $@.dir + mkdir $@.dir + ln $(TZDATA_DIST) $@.dir +@@ -1273,8 +1329,11 @@ + (cd $@.dir && \ + $$TAR -cf - \ + $(TZDATA_DIST) pacificnew | \ +- gzip $(GZIPFLAGS)) >$@.out +- mv $@.out $@ ++ gzip $(GZIPFLAGS)) >$(@:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) \ ++ $$(cd $@.dir && \ ++ ls $(TZDATA_DIST) pacificnew | sed 's,^,$@.dir/,') ++ touch $@ + + # Create a tailored tarball suitable for TZUpdater and compatible tools. + # For example, 'make DATAFORM=vanguard tailored_tarballs' makes a tarball +@@ -1283,7 +1342,7 @@ + # traditional tarball, as data entries are put into 'etcetera' even if they + # came from some other source file. However, the effect should be the same + # for ordinary use, which reads all the source files. +-tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out ++tzdata$(VERSION)-tailored.tar.gz.t: set-timestamps.out + rm -fr $@.dir + mkdir $@.dir + : The dummy pacificnew pacifies TZUpdater 2.3.1 and earlier. +@@ -1295,7 +1354,7 @@ + cd $@.dir && \ + $(CREATE_EMPTY) $(PRIMARY_YDATA) $(NDATA) backward \ + $$pacificnew +- (grep '^#' tzdata.zi && echo && cat $(DATAFORM).zi) \ ++ (sed '/^#/!d' tzdata.zi && echo && cat $(DATAFORM).zi) \ + >$@.dir/etcetera + touch -mr tzdata.zi $@.dir/etcetera + sed -n \ +@@ -1316,24 +1375,29 @@ + ln $$links $@.dir + $(SETUP_TAR) && \ + (cd $@.dir && \ +- $$TAR -cf - * | gzip $(GZIPFLAGS)) >$@.out +- mv $@.out $@ ++ $$TAR -cf - *) | gzip $(GZIPFLAGS) >$(@:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) \ ++ $$(cd $@.dir && ls * | sed 's,^,$@.dir/,') ++ touch $@ + +-tzdb-$(VERSION).tar.lz: set-timestamps.out set-tzs-timestamp.out ++tzdb-$(VERSION).tar.lz.t: set-timestamps.out set-tzs-timestamp.out + rm -fr tzdb-$(VERSION) + mkdir tzdb-$(VERSION) + ln $(ENCHILADA) tzdb-$(VERSION) + $(SET_TIMESTAMP) tzdb-$(VERSION) tzdb-$(VERSION)/* + $(SETUP_TAR) && \ +- $$TAR -cf - tzdb-$(VERSION) | lzip -9 >$@.out +- mv $@.out $@ ++ $$TAR -cf - tzdb-$(VERSION) | lzip -9 >$(@:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) tzdb-$(VERSION) ++ touch $@ + +-tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz +-tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz +-tzdata$(VERSION)-rearguard.tar.gz.asc: tzdata$(VERSION)-rearguard.tar.gz +-tzdb-$(VERSION).tar.lz.asc: tzdb-$(VERSION).tar.lz ++tzcode$(VERSION).tar.gz.asc.t: tzcode$(VERSION).tar.gz.t ++tzdata$(VERSION).tar.gz.asc.t: tzdata$(VERSION).tar.gz.t ++tzdata$(VERSION)-rearguard.tar.gz.asc.t: tzdata$(VERSION)-rearguard.tar.gz.t ++tzdb-$(VERSION).tar.lz.asc.t: tzdb-$(VERSION).tar.lz.t + $(ALL_ASC): +- $(GPG) --armor --detach-sign $? ++ $(GPG) --armor --detach-sign $(?:.t=) ++ $(SET_TIMESTAMP) $(@:.t=) $(?:.t=) ++ touch $@ + + TYPECHECK_CFLAGS = $(CFLAGS) -DTYPECHECK -D__time_t_defined -D_TIME_T + typecheck: long-long.ck unsigned.ck +--- contrib/tzdata/NEWS.orig ++++ contrib/tzdata/NEWS +@@ -1,5 +1,274 @@ + News for the tz database + ++Release 2026a - 2026-04-22 23:06:43 -0700 ++ ++ Briefly: ++ British Columbia moved to permanent -07 on 2026-03-09. ++ Some more overflow bugs have been fixed in zic. ++ ++ Changes to future timestamps ++ ++ British Columbia’s 2026-03-08 spring forward was its last ++ foreseeable clock change, as it moved to permanent -07 thereafter. ++ (Thanks to Arthur David Olson.) Although the change to permanent ++ -07 legally took place on 2026-03-09, temporarily model the change ++ to occur on 2026-11-01 at 02:00 instead. This works around a ++ limitation in CLDR v48.2 (2026-03-17). This temporary hack is ++ planned to be removed after CLDR is fixed. ++ ++ Changes to code ++ ++ zic no longer mishandles a last transition to a new time type. ++ ++ zic no longer overflows a buffer when generating a TZ string like ++ "PST-167:59:58PDT-167:59:59,M11.5.6/-167:59:59,M12.5.6/-167:59:59", ++ which can occur with adversarial input. (Thanks to Naveed Khan.) ++ ++ zic no longer generates a longer TZif file than necessary when ++ an earlier time zone abbreviation is a suffix of a later one. ++ As a nice side effect, zic no longer overflows a buffer when given ++ a long series of abbreviations, each a suffix of the next. ++ (Buffer overflow reported by Arthur Chan.) ++ ++ zic no longer overflows an int when processing input like ‘Zone ++ Ouch 2147483648:00:00 - LMT’. The int overflow can lead to buffer ++ overflow in adversarial cases. (Thanks to Naveed Khan.) ++ ++ zic now checks for signals more often. ++ ++ ++Release 2026a - 2026-03-01 22:59:49 -0800 ++ ++ Briefly: ++ Moldova has used EU transition times since 2022. ++ The “right” TZif files are no longer installed by default. ++ -DTZ_RUNTIME_LEAPS=0 disables runtime support for leap seconds. ++ TZif files are no longer limited to 50 bytes of abbreviations. ++ zic is no longer limited to 50 leap seconds. ++ Several integer overflow bugs have been fixed. ++ ++ Changes to past and future timestamps ++ ++ Since 2022 Moldova has observed EU transition times, that is, it ++ has sprung forward at 03:00, not 02:00, and has fallen back at ++ 04:00, not 03:00. (Thanks to Heitor David Pinto.) ++ ++ Changes to data ++ ++ Remove Europe/Chisinau from zonenow.tab, as it now agrees with ++ Europe/Athens for future timestamps. ++ ++ Changes to build procedure ++ ++ The Makefile no longer by default installs an alternate set ++ of TZif files for system clocks that count leap seconds. ++ Install with ‘make REDO=posix_right’ to get the old default, ++ which is rarely used in major downstream distributions. ++ If your system clock counts leap seconds (contrary to POSIX), ++ it is better to install with ‘make REDO=right_only’. ++ This change does not affect the leapseconds file, which is still ++ installed as before. ++ ++ The Makefile’s POSIXRULES option, which was declared obsolete in ++ release 2019b, has been removed. The Makefile’s build procedure ++ thus no longer optionally installs the obsolete posixrules file. ++ ++ Changes to code ++ ++ Compiling with the new option -DTZ_RUNTIME_LEAPS=0 disables ++ runtime support for leap seconds. Although this conforms to ++ POSIX, shrinks tzcode’s attack surface, and is more efficient, ++ it fails to support Internet RFC 9636’s leap seconds. ++ ++ zic now can generate, and localtime.c can now use, TZif files that ++ hold up to 256 bytes of abbreviations, counting trailing NULs. ++ The previous limit was 50 bytes, and some tzdata TZif files were ++ already consuming 40 bytes. zic -v warns if it generates a file ++ that exceeds the old 50-byte limit. ++ ++ zic -L can now generate TZif files with more than 50 leap seconds. ++ This helps test TZif readers not limited to 50 leap seconds, as ++ tzcode’s localtime.c is; it has little immediate need for ++ practical timekeeping as there have been only 27 leap seconds and ++ possibly there will be no more, due to planned changes to UTC. ++ zic -v warns if its output exceeds the old 50-second limit. ++ ++ localtime.c no longer accesses the posixrules file generated by ++ zic -p. Hence for obsolete and nonconforming settings like ++ TZ="AST4ADT" it now typically falls back on US DST rules, rather ++ than attempting to override this fallback with the contents of the ++ posixrules file. This removes library support that was declared ++ obsolete in release 2019b, and fixes some undefined behavior. ++ (Undefined behavior reported by GitHub user Naveed8951.) ++ ++ The posix2time, posix2time_z, time2posix, and time2posix_z ++ functions now set errno=EOVERFLOW and return ((time_t) -1) if the ++ result is not representable. Formerly they had undefined behavior ++ that could in practice result in crashing, looping indefinitely, ++ or returning an incorrect result. As before, these functions are ++ defined only when localtime.c is compiled with the -DSTD_INSPIRED ++ option. ++ ++ Some other undefined behavior, triggered by TZif files containing ++ outlandish but conforming UT offsets or leap second corrections, ++ has also been fixed. (Some of these bugs reported by Naveed8951.) ++ ++ localtime.c no longer rejects TZif files that exactly fit in its ++ internal structures, fixing off-by-one typos introduced in 2014g. ++ ++ zic no longer generates a no-op transition when ++ simultaneous Rule and Zone changes cancel each other out. ++ This occurs in tzdata only in Asia/Tbilisi on 1997-03-30. ++ (Thanks to Renchunhui for a test case showing the bug.) ++ ++ zic no longer assumes you can fflush a read-only stream. ++ (Problem reported by Christos Zoulas.) ++ ++ zic no longer generates UT offsets equal to -2**31 and localtime.c ++ no longer accepts them, as they can cause trouble in both ++ localtime.c and its callers. RFC 9636 prohibits such offsets. ++ ++ zic -p now warns that the -p option is obsolete and likely ++ ineffective. ++ ++ ++Release 2025c - 2025-12-10 14:42:37 -0800 ++ ++ Briefly: ++ Several code changes for compatibility with FreeBSD. ++ ++ Changes to past timestamps ++ ++ Baja California agreed with California’s DST rules in 1953 and in ++ 1961 through 1975, instead of observing standard time all year. ++ (Thanks to Alois Treindl.) ++ ++ Changes to build procedure ++ ++ Files in distributed tarballs now have correct commit times. ++ Formerly, the committer’s time zone was incorrectly ignored. ++ ++ Distribution products (*.asc, *.gz, and *.lz) now have ++ reproducible timestamps. Formerly, only the contents of the ++ compressed tarballs had reproducible timestamps. ++ ++ By default, distributed formatted man pages (*.txt) now use UTF-8 ++ and are left-adjusted more consistently. A new Makefile macro ++ MANFLAGS can override these defaults. (Thanks to G. Branden ++ Robinson for inspiring these changes.) ++ ++ Changes to code ++ ++ An unset TZ is no longer invalid when /etc/localtime is missing, ++ and is abbreviated "UTC" not "-00". This reverts to 2024b behavior. ++ (Problem and patch reported by Dag-Erling Smørgrav.) ++ ++ New function offtime_r, short for fixed-offset localtime_rz. ++ It is defined if STD_INSPIRED is defined. ++ (Patch from Dag-Erling Smørgrav.) ++ ++ tzset etc. are now more cautious about questionable TZ settings. ++ Privileged programs now reject TZ settings that start with '/', ++ unless they are TZDEFAULT (default "/etc/localtime") or ++ start with TZDIR then '/' (default "/usr/share/zoneinfo/"). ++ Unprivileged programs now require files to be regular files ++ and reject relative names containing ".." directory components; ++ formerly, only privileged programs did those two things. ++ These changes were inspired by similar behavior in FreeBSD. ++ On NetBSD, unprivileged programs now use O_REGULAR to check ++ whether a TZ setting starting with '/' names a regular file, ++ avoiding a minor security race still present elsewhere. ++ TZ strings taken from tzalloc arguments are now treated with ++ no less caution than TZ strings taken from the environment, as ++ the old undocumented behavior would have been hard to explain. ++ tzset etc. no longer use the ‘access’ system call to check access; ++ instead they now use the system calls issetugid, getauxval, ++ getresuid/getresgid, and geteuid/getegid/getuid/getgid (whichever ++ first works) to test whether a program is privileged. ++ Compile with -DHAVE_SYS_AUXV_H=[01] to enable or disable ++ <sys/auxv.h> which (if it defines AT_SECURE) enables getauxval, ++ and compile with -DHAVE_ISSETUGID=[01], -DHAVE_GETRESUID=[01], and ++ -DHAVE_GETEUID=[01] to enable or disable the other calls’ use. ++ ++ The new CFLAGS option -DTZ_CHANGE_INTERVAL=N makes tzset etc. ++ check for TZif file changes if the in-memory data are N seconds ++ old or more, and are derived from the TZ environment variable. ++ This is intended for platforms that want tzset etc. to reflect ++ changes to whatever file TZ selects (including changes to ++ /etc/localtime if TZ is unset). If N is negative (the default) ++ these checks are omitted; this is the traditional behavior. ++ ++ The new CFLAGS options -DHAVE_STRUCT_STAT_ST_CTIM=0 and ++ -DHAVE_STRUCT_TIMESPEC=0 port to non-POSIX.1-2008 platforms ++ that lack st_ctim and struct timespec, respectively. ++ On these platforms, the code falls back on st_ctime to ++ implement -DTZ_CHANGE_INTERVAL=N. ++ ++ tzset etc. now treat ' ' like '_' in time zone abbreviations, ++ just as they treat other invalid bytes. This continues the ++ transition begun in release 96k, which removed spaces in tzdata ++ because the spaces break time string parsers. ++ ++ The new CFLAGS option -DTHREAD_PREFER_SINGLE causes tzcode ++ in single-threaded processes to avoid locks, as FreeBSD does. ++ This can save time in single-threaded apps. The threadedness ++ testing costs CPU time and energy in multi-threaded apps. ++ New options -DHAVE___ISTHREADED and -DHAVE_SYS_SINGLE_THREADED_H ++ can help configure how to test for single-threadedness. ++ ++ The new CFLAGS option -DTHREAD_RWLOCK uses read-write locks, as ++ macOS does, instead of mutexes. This saves real time when TZ is ++ rarely changing and many threads call tzcode simultaneously. ++ It costs more CPU time and energy. ++ ++ The new CFLAGS option -TTHREAD_TM_MULTI causes localtime to return ++ a pointer to thread-specific memory, as FreeBSD does, instead of ++ to the same memory in all threads. This supports nonportable ++ programs that incorrectly use localtime instead of localtime_r. ++ This option affects gmtime and offtime similarly to localtime. ++ Because the corresponding storage is freed on thread exit, this ++ option is incompatible with POSIX.1-2024 and earlier. It also ++ costs CPU time and memory. ++ ++ tzfree now preserves errno, consistently with POSIX.1-2024 ‘free’. ++ ++ tzcode now uses mempcpy if available, guessing its availability. ++ Compile with -DHAVE_MEMPCPY=1 or 0 to override the guess. ++ ++ tzcode now uses strnlen to improve asymptotic performance a bit. ++ Compile with -DHAVE_STRNLEN=0 if your platform lacks it. ++ ++ tzcode now hand-declares unistd.h-provided symbols like getopt ++ if HAVE_UNISTD_H=0, not if HAVE_POSIX_DECLS=0. ++ ++ tzset etc. now have an experimental OPENAT_TZDIR option; ++ see Makefile and localtime.c for details. ++ ++ On platforms like GNU/Hurd that do not define PATH_MAX, ++ exceedingly long TZ strings no longer fail merely because they ++ exceed an arbitrary file name length limit imposed by tzcode. ++ ++ zic has new options inspired by FreeBSD. ‘-D’ skips creation of ++ output ancestor directories, ‘-m MODE’ sets output files’ mode, ++ and ‘-u OWNER[:GROUP]’ sets output files’ owner and group. ++ ++ zic now uses the fdopen function, which was standardized by ++ POSIX.1-1988 and is now safe to use in portable code. ++ This replaces its use of the older umask function, which ++ complicated maintenance. ++ ++ Changes to commentary ++ ++ The leapseconds file contains commentary about the IERS and NIST ++ last-modified and expiration timestamps for leap second data. ++ (Thanks to Judah Levine.) ++ ++ Commentary now also uses characters from the set –‘’“”•≤ as this ++ can be useful and should work with current applications. This ++ also affects data in iso3166.tab and zone1970.tab, which now ++ contain strings like “Côte d’Ivoire” instead of “Côte d'Ivoire”. ++ ++ + Release 2025b - 2025-03-22 13:40:46 -0700 + + Briefly: +--- contrib/tzdata/README.orig ++++ contrib/tzdata/README +@@ -1,8 +1,8 @@ + README for the tz distribution + +-"Where do I set the hands of the clock?" -- Les Tremayne as The King +-"Oh that--you can set them any place you want." -- Frank Baxter as The Scientist +- (from the Bell System film "About Time") ++“Where do I set the hands of the clock?” – Les Tremayne as The King ++“Oh that – you can set them any place you want.” – Frank Baxter as The Scientist ++ (from the Bell System film “About Time”) + + The Time Zone Database (called tz, tzdb or zoneinfo) contains code and + data that represent the history of local time for many representative +@@ -13,12 +13,12 @@ + See <https://www.iana.org/time-zones/repository/tz-link.html> or the + file tz-link.html for how to acquire the code and data. + +-Once acquired, read the leading comments in the file "Makefile" ++Once acquired, read the leading comments in the file ‘Makefile’ + and make any changes needed to make things right for your system, + especially when using a platform other than current GNU/Linux. + + Then run the following commands, substituting your desired +-installation directory for "$HOME/tzdir": ++installation directory for ‘$HOME/tzdir’: + + make TOPDIR="$HOME/tzdir" install + "$HOME/tzdir/usr/bin/zdump" -v America/Los_Angeles +@@ -39,12 +39,12 @@ + fixes and enhancements are welcome. Please see the file CONTRIBUTING + for details. + +-Thanks to these Time Zone Caballeros who've made major contributions to the ++Thanks to these Time Zone Caballeros who’ve made major contributions to the + time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz; + Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to + Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales + for testing work, and to Gwillim Law for checking local mean time data. +-Thanks in particular to Arthur David Olson, the project's founder and first ++Thanks in particular to Arthur David Olson, the project’s founder and first + maintainer, to whom the time zone community owes the greatest debt of all. + None of them are responsible for remaining errors. + +--- contrib/tzdata/SECURITY.orig ++++ contrib/tzdata/SECURITY +@@ -1,7 +1,7 @@ + Please report any sensitive security-related bugs via email to the + tzdb designated coordinators, currently Paul Eggert + <eggert@cs.ucla.edu> and Tim Parenti <tim@timtimeonline.com>. +-Put "tzdb security" at the start of your email's subject line. ++Put “tzdb security” at the start of your email’s subject line. + We prefer communications to be in English. + + You should receive a response within a week. If not, please follow up +--- contrib/tzdata/africa.orig ++++ contrib/tzdata/africa +@@ -4,9 +4,9 @@ + # 2009-05-17 by Arthur David Olson. + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (2018-05-27): + # +@@ -115,8 +115,9 @@ + -1:00 - %z + + # Chad ++# Fort-Lamy was renamed to N’Djamena on 1973-04-06. + # Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone Africa/Ndjamena 1:00:12 - LMT 1912 Jan 1 # N'Djamena ++Zone Africa/Ndjamena 1:00:12 - LMT 1912 Jan 1 # Fort-Lamy + 1:00 - WAT 1979 Oct 14 + 1:00 1:00 WAST 1980 Mar 8 + 1:00 - WAT +--- contrib/tzdata/antarctica.orig ++++ contrib/tzdata/antarctica +@@ -3,13 +3,10 @@ + # This file is in the public domain, so clarified as of + # 2009-05-17 by Arthur David Olson. + +-# From Paul Eggert (1999-11-15): +-# To keep things manageable, we list only locations occupied year-round; see +-# COMNAP - Stations and Bases +-# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/ +-# and +-# Summary of the Peri-Antarctic Islands (1998-07-23) +-# http://www.spri.cam.ac.uk/bob/periant.htm ++# From Paul Eggert (2025-08-16): ++# To keep things manageable, list only locations occupied year-round; see ++# Antarctic Facilities Information ++# https://www.comnap.aq/antarctic-facilities-information + # for information. + # Unless otherwise specified, we have no time zone information. + +@@ -144,6 +141,7 @@ + # China - year-round bases + # Great Wall, King George Island, -6213-05858, since 1985-02-20 + # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26 ++# Qinling, Inexpressible I, Terra Nova Bay, -7456+16343, since 2024-02-07 + + # France - year-round bases (also see "France & Italy") + # +--- contrib/tzdata/asia.orig ++++ contrib/tzdata/asia +@@ -4,9 +4,9 @@ + # 2009-05-17 by Arthur David Olson. + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (2019-07-11): + # +--- contrib/tzdata/australasia.orig ++++ contrib/tzdata/australasia +@@ -937,9 +937,9 @@ + # NOTES + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (2018-11-18): + # +@@ -1988,6 +1988,7 @@ + # From Paul Eggert (2018-11-19): + # The 1921-01-15 introduction of standard time is in Shanks; it is also in + # "Standard Time Throughout the World", US National Bureau of Standards (1935), ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular406.pdf + # page 3, which does not give the UT offset. In response to a comment by + # Phake Nick I set the Nauru time of occupation by Japan to + # 1942-08-29/1945-09-08 by using dates from: +@@ -2055,9 +2056,10 @@ + # https://webspace.science.uu.nl/~gent0113/idl/idl_alaska_samoa.htm + + # Although Shanks & Pottenger says they both switched to UT -11:30 +-# in 1911, and to -11 in 1950. many earlier sources give -11 ++# in 1911, and to -11 in 1950, many earlier sources give -11 + # for American Samoa, e.g., the US National Bureau of Standards + # circular "Standard Time Throughout the World", 1932. ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular399.pdf + # Assume American Samoa switched to -11 in 1911, not 1950, + # and that after 1950 they agreed until (western) Samoa skipped a + # day in 2011. Assume also that the Samoas follow the US and New +--- contrib/tzdata/backzone.orig ++++ contrib/tzdata/backzone +@@ -2,10 +2,10 @@ + + # This file is in the public domain. + +-# This file is by no means authoritative; if you think you know +-# better, go ahead and edit it (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# This file is by no means authoritative; if you think you know better, ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # When proposing changes to this file, please use 'git format-patch' + # format, either by attaching the resulting .patch file to your email, +@@ -1757,13 +1757,12 @@ + # Midway + # + # From Mark Brader (2005-01-23): +-# [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies, +-# published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3] ++# [<https://www.timetableimages.com/ttimages/pa/pa36/pa36.pdf>] + # reproduced a Pan American Airways timetable from 1936, for their weekly + # "Orient Express" flights between San Francisco and Manila, and connecting + # flights to Chicago and the US East Coast. As it uses some time zone + # designations that I've never seen before:.... +-# Fri. 6:30A Lv. HONOLOLU (Pearl Harbor), H.I. H.L.T. Ar. 5:30P Sun. ++# Fri. 6:30A Lv. HONOLULU (Pearl Harbor), H.I. . H.L.T. Ar. 5:30P Sun. + # " 3:00P Ar. MIDWAY ISLAND . . . . . . . . . M.L.T. Lv. 6:00A " + # + Zone Pacific/Midway -11:49:28 - LMT 1901 +--- contrib/tzdata/calendars.orig ++++ contrib/tzdata/calendars +@@ -16,30 +16,9 @@ + + Russia + +-From Chris Carrier (1996-12-02): +-On 1929-10-01 the Soviet Union instituted an "Eternal Calendar" +-with 30-day months plus 5 holidays, with a 5-day week. +-On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the +-Gregorian calendar while retaining the 6-day week; on 1940-06-27 it +-reverted to the 7-day week. With the 6-day week the usual days +-off were the 6th, 12th, 18th, 24th and 30th of the month. +-(Source: Evitiar Zerubavel, _The Seven Day Circle_) +- +- +-Mark Brader reported a similar story in "The Book of Calendars", edited +-by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But: +- +-From: Petteri Sulonen (via Usenet) +-Date: 14 Jan 1999 00:00:00 GMT +-... +- +-If your source is correct, how come documents between 1929 and 1940 were +-still dated using the conventional, Gregorian calendar? +- +-I can post a scan of a document dated December 1, 1934, signed by +-Yenukidze, the secretary, on behalf of Kalinin, the President of the +-Executive Committee of the Supreme Soviet, if you like. +- ++Soviet Russia adopted the Gregorian calendar on 1918-02-14. ++It also used 5- and 6-day work weeks at times, in parallel with the ++Gregorian calendar; see <https://en.wikipedia.org/wiki/Soviet_calendar>. + + + Sweden (and Finland) +--- contrib/tzdata/checknow.awk.orig ++++ contrib/tzdata/checknow.awk +@@ -50,5 +50,10 @@ + status = 1 + } + } ++ if (now_out) { ++ for (data in zones) { ++ printf "%s=%s\n", now, zones[data] >>now_out ++ } ++ } + exit status + } +--- contrib/tzdata/etcetera.orig ++++ contrib/tzdata/etcetera +@@ -20,7 +20,8 @@ + # which load the "UTC" file to handle seconds properly. + Zone Etc/UTC 0 - UTC + +-# Functions like gmtime load the "GMT" file to handle leap seconds properly. ++# If leap second support is enabled, functions like gmtime ++# load the "GMT" file to handle leap seconds properly. + # Vanguard section, which works with most .zi parsers. + #Zone GMT 0 - GMT + # Rearguard section, for TZUpdater 2.3.2 and earlier. +--- contrib/tzdata/europe.orig ++++ contrib/tzdata/europe +@@ -4,9 +4,9 @@ + # 2009-05-17 by Arthur David Olson. + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (2017-02-10): + # +@@ -42,7 +42,7 @@ + # <https://www.jstor.org/stable/1774359>. He writes: + # "It is requested that corrections and additions to these tables + # may be sent to Mr. John Milne, Royal Geographical Society, +-# Savile Row, London." Nowadays please email them to tz@iana.org. ++# Savile Row, London." Nowadays please see the file CONTRIBUTING. + # + # Byalokoz EL. New Counting of Time in Russia since July 1, 1919. + # This Russian-language source was consulted by Vladimir Karpinsky; see +@@ -54,7 +54,7 @@ + # Десятая гос. тип., 1919. + # http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf + # +-# Brazil's Divisão Serviço da Hora (DSHO), ++# Brazil's Divisão de Serviços da Hora (DISHO) + # History of Summer Time + # <http://pcdsh01.on.br/HISTHV.htm> + # (1998-09-21, in Portuguese) +@@ -914,7 +914,7 @@ + Rule Belgium 1923 only - Apr 21 23:00s 1:00 S + Rule Belgium 1924 only - Mar 29 23:00s 1:00 S + Rule Belgium 1925 only - Apr 4 23:00s 1:00 S +-# DSH writes that a royal decree of 1926-02-22 specified the Sun following 3rd ++# DISHO writes that a royal decree of 1926-02-22 specified the Sun following 3rd + # Sat in Apr (except if it's Easter, in which case it's one Sunday earlier), + # to Sun following 1st Sat in Oct, and that a royal decree of 1928-09-15 + # changed the transition times to 02:00 GMT. +@@ -1041,9 +1041,19 @@ + + # Greenland + # +-# From Paul Eggert (2004-10-31): ++# From Paul Eggert (2026-01-22): ++# During World War II, Greenland was effectively independent of Denmark and ++# observed daylight saving time. TIME, volume 37, page 23 (1941-04-21) ++# <https://time.com/archive/6770243/war-peace-greenlands-icy-mountains/> says, ++# "Penfield and West made their way to the U.S.'s most northerly consulate. ++# They were astonished to find that Greenlanders, with almost 24 hours of ++# sunlight a day during the summer, have daylight saving time." ++# As the details are unknown they are omitted from the data for now. ++# + # During World War II, Germany maintained secret manned weather stations in + # East Greenland and Franz Josef Land, but we don't know their time zones. ++# Also, they're likely out of scope for the database ++# as we lack resources to track every bit of military activity. + # My source for this is Wilhelm Dege's book mentioned under Svalbard. + # + # From Paul Eggert (2017-12-10): +@@ -1310,6 +1320,13 @@ + # France + # Monaco + ++# From Robert H. van Gent (2025-07-21): ++# The most recent issue of the Annuaire [par le Bureau des Longitudes] ++# on Gallica (2021) ... lists information for France ++# https://gallica.bnf.fr/ark:/12148/bpt6k9127672b/f52.item ++# From Paul Eggert (2025-07-21): ++# Go with the 2020 Annuaire (published 2021) except as noted below. ++ + # From Ciro Discepolo (2000-12-20): + # + # Henri Le Corre, Régimes horaires pour le monde entier, Éditions +@@ -1371,7 +1388,6 @@ + # problems in Algiers, Monaco and Tunis. + + # +-# Shank & Pottenger seem to use '24:00' ambiguously; resolve it with Whitman. + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S + Rule France 1916 only - Jun 14 23:00s 1:00 S + Rule France 1916 1919 - Oct Sun>=1 23:00s 0 - +@@ -1383,9 +1399,25 @@ + Rule France 1921 only - Mar 14 23:00s 1:00 S + Rule France 1921 only - Oct 25 23:00s 0 - + Rule France 1922 only - Mar 25 23:00s 1:00 S +-# DSH writes that a law of 1923-05-24 specified 3rd Sat in Apr at 23:00 to 1st +-# Sat in Oct at 24:00; and that in 1930, because of Easter, the transitions +-# were Apr 12 and Oct 5. Go with Shanks & Pottenger. ++# From Robert H. van Gent (2025-07-22): ++# There is a curious history behind the erroneous date for the start of ++# daylight saving in France in 1923 as listed in the current issues of ++# the Annuaire du Bureau des Longitudes. [See:] ++# https://lists.iana.org/hyperkitty/list/tz@iana.org/message/MYQEJMSXO2AIEZ3UIXZKMTTAIPY7KNT2/ ++# From Brian Inglis (2025-07-23): ++# Légifrance JORF No. 0073 du 15 mars 1922 ++# https://www.legifrance.gouv.fr/jorf/jo/id/JORFCONT000000008324 ++# Légifrance JORF No. 0139 du 25 mai 1923 ++# https://www.legifrance.gouv.fr/jorf/jo/id/JORFCONT000000008416 ++# From Paul Eggert (2025-07-23): ++# The latter specifies March's last Saturday at 23:00 to October's first ++# Saturday at 24:00, except that if neighboring allies agree the dates ++# can be moved to April's third Saturday and September's third Saturday. ++# Apparently spring 1923 was tricky. DISHO writes that in 1930, ++# because of Easter, the transitions were Apr 12 and Oct 5. ++# Use the 2020 Annuaire dates, except for spring 1923 where ++# Shanks & Pottenger's May 26 matches the dates given in the 1924 and ++# 1961-2001 issues of the Annuaire. + Rule France 1922 1938 - Oct Sat>=1 23:00s 0 - + Rule France 1923 only - May 26 23:00s 1:00 S + Rule France 1924 only - Mar 29 23:00s 1:00 S +@@ -1935,7 +1967,6 @@ + + # From Stepan Golosunov (2016-03-07): + # the act of the government of the Republic of Moldova Nr. 132 from 1990-05-04 +-# http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=2 + # ... says that since 1990-05-06 on the territory of the Moldavian SSR + # time would be calculated as the standard time of the second time belt + # plus one hour of the "summer" time. To implement that clocks would be +@@ -1990,9 +2021,61 @@ + # says the 2014-03-30 spring-forward transition was at 02:00 local time. + # Guess that since 1997 Moldova has switched one hour before the EU. + ++# From Heitor David Pinto (2026-02-22): ++# Soviet Moldovan resolution 132 of 1990 defined the summer time period from ++# the last Sunday in March at 2:00 to the last Sunday in September at 3:00, ++# matching the dates used in most of Europe at the time: ++# https://web.archive.org/web/20211107050832/http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=1 ++# ++# It seems that in 1996 Moldova changed the end date to October like most of ++# Europe, but kept the transitions at 2:00 and 3:00 rather than 1:00 UTC, ++# which would have been locally 3:00 and 4:00.... ++# ++# The notices in the Moldovan government website and broadcaster showed the ++# transitions at 2:00 and 3:00 until 2021: ++# 2015 https://old.gov.md/en/node/7304 ++# 2016 https://old.gov.md/en/node/12587 ++# 2017 https://old.gov.md/en/node/20654 ++# 2017 https://old.gov.md/en/content/moldova-upholds-winter-time-night-28-29-october ++# 2018 https://old.gov.md/en/content/moldova-switch-summer-time ++# 2018 https://old.gov.md/en/content/cabinet-ministers-informs-about-switch-winter-time-28-october ++# 2019 https://old.gov.md/en/content/moldova-switch-summer-time-31-march ++# 2019 https://old.gov.md/en/node/31122 ++# 2020 https://old.gov.md/en/node/32771 ++# 2020 https://old.gov.md/en/node/34497 ++# 2021 https://trm.md/ro/social/moldova-trece-in-aceasta-noapte-la-ora-de-vara ++# 2021 https://trm.md/en/social/republica-moldova-trece-la-ora-de-iarna1 ++# ++# However, since 2022, the notices showed the transitions at 3:00 and 4:00, ++# matching the EU rule at 1:00 UTC: ++# 2022 https://trm.md/en/social/in-acest-weekend-republica-moldova-trece-la-ora-de-vara ++# 2022 https://old.gov.md/en/content/moldova-switch-winter-time ++# 2023 https://moldova1.md/p/6587/ora-de-vara-2023-cum-schimbam-acele-ceasornicelor-si-cand-trecem-la-ora-de-vara ++# 2023 https://old.gov.md/en/node/46662 ++# 2024 https://moldova1.md/p/26535/republica-moldova-trece-la-ora-de-vara-in-acest-weekend ++# 2024 https://moldova1.md/p/37768/republica-moldova-trece-in-aceasta-noapte-la-ora-de-iarna ++# 2025 https://moldova1.md/p/46349/republica-moldova-trece-la-ora-de-vara-pe-30-martie-cum-ne-afecteaza-si-ce-recomanda-medicii ++# 2025 https://moldova1.md/p/60469/republica-moldova-trece-la-ora-de-iarna-ceasurile-se-dau-inapoi-cu-o-ora ++# ++# It seems that the changes to the end date and transition times were just ++# done in practice without formally changing the resolution. In late 2025, the ++# government said that the Soviet resolution was still in force, and proposed ++# a new resolution to replace it and formally establish the EU rule: ++# ... based on the notices, it seems that in practice Moldova already ++# uses the EU rule since 2022. This was also the year when Moldova applied to ++# join the EU. ++# ++# From Robert Bastian (2026-02-26): ++# This has been approved and published in the government gazette: ++# https://monitorul.gov.md/ro/monitorul/view/pdf/3234/part/2#page=27 ++# ++# From Paul Eggert (2026-02-24): ++# Also see Svetlana Rudenko, "Moldova abandons the 'Soviet era'", Logos Press, ++# 2026-02-21 <https://logos-pres.md/en/news/moldova-abandons-the-soviet-era/>. ++ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S +-Rule Moldova 1997 max - Oct lastSun 3:00 0 - ++Rule Moldova 1997 2021 - Mar lastSun 2:00 1:00 S ++Rule Moldova 1997 2021 - Oct lastSun 3:00 0 - + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Europe/Chisinau 1:55:20 - LMT 1880 +@@ -2005,7 +2088,8 @@ + 2:00 Russia EE%sT 1992 + 2:00 E-Eur EE%sT 1997 + # See Romania commentary for the guessed 1997 transition to EU rules. +- 2:00 Moldova EE%sT ++ 2:00 Moldova EE%sT 2022 ++ 2:00 EU EE%sT + + # Poland + +@@ -2096,12 +2180,10 @@ + # all clocks therefore having to be advanced or set back correspondingly ... + + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-# From Tim Parenti (2024-07-01), per Paul Eggert (1999-01-30): +-# DSH writes in their history that Decreto 1469 of 1915-03-30 established +-# summer time and that, "despite" this, the change to the clocks was not done +-# every year, depending on what Spain did, because of railroad schedules. +-# In fact, that decree had nothing to do with DST; rather, it regulated the +-# sending of time signals. But we do see linkage to Spain in the 1920s below. ++# From Tim Parenti (2024-07-01): ++# Decreto 1469 of 1915-03-30 ... had nothing to do with DST; ++# rather it regulated the sending of time signals. ++# But we do see linkage to Spain in the 1920s below. + # https://dre.pt/dr/detalhe/decreto/1469-1915-285721 + # https://dre.pt/application/conteudo/285721 + # +@@ -2393,7 +2475,7 @@ + # Nine O'clock <http://www.nineoclock.ro/POL/1778pol.html> + # (1998-10-23) reports that the switch occurred at + # 04:00 local time in fall 1998. For lack of better info, +-# assume that Romania and Moldova switched to EU rules in 1997, ++# assume that Romania switched to EU rules in 1997, + # the same year as Bulgaria. + # + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +--- contrib/tzdata/leap-seconds.list.orig ++++ contrib/tzdata/leap-seconds.list +@@ -60,15 +60,15 @@ + # + # The following line shows the last update of this file in NTP timestamp: + # +-#$ 3945196800 ++#$ 3976686858 + # + # 2) Expiration date of the file given on a semi-annual basis: last June or last December + # +-# File expires on 28 December 2025 ++# File expires on 28 December 2026 + # + # Expire date in NTP timestamp: + # +-#@ 3975868800 ++#@ 4007404800 + # + # + # LIST OF LEAP SECONDS +@@ -117,4 +117,4 @@ + # please see the readme file in the 'source' directory : + # https://hpiers.obspm.fr/iers/bul/bulc/ntp/sources/README + # +-#h 848434d5 570f7ea8 d79ba227 a00fc821 f608e2d4 ++#h 2e101270 4e6749f8 2f1792b7 14a0c188 36bb19d6 +--- contrib/tzdata/leapseconds.orig ++++ contrib/tzdata/leapseconds +@@ -5,7 +5,8 @@ + # This file is generated automatically from the data in the public-domain + # NIST/IERS format leap-seconds.list file, which can be copied from + # <https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list> +-# or, in a variant with different comments, from ++# or via a less-secure protocol and with different comments and ++# less volatile last-modified and expiration timestamps, from + # <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>. + # For more about leap-seconds.list, please see + # The NTP Timescale and Leap Seconds +@@ -69,11 +70,17 @@ + # Any additional leap seconds will come after this. + # This Expires line is commented out for now, + # so that pre-2020a zic implementations do not reject this file. +-#Expires 2025 Dec 28 00:00:00 ++#Expires 2026 Dec 28 00:00:00 + +-# POSIX timestamps for the data in this file: +-#updated 1736208000 (2025-01-07 00:00:00 UTC) +-#expires 1766880000 (2025-12-28 00:00:00 UTC) ++# Here are POSIX timestamps for the data in this file. ++# "#updated" gives the last time the leap seconds data changed ++# or, if this file was derived from the IERS leap-seconds.list, ++# the last time that file changed in any way. ++# "#expires" gives the first time this file might be wrong; ++# if this file was derived from the IERS leap-seconds.list, ++# this is typically a bit less than one year after "updated". ++#updated 1767698058 (2026-01-06 11:14:18 UTC) ++#expires 1798416000 (2026-12-28 00:00:00 UTC) + + # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) +-# File expires on 28 December 2025 ++# File expires on 28 December 2026 +--- contrib/tzdata/leapseconds.awk.orig ++++ contrib/tzdata/leapseconds.awk +@@ -23,7 +23,8 @@ + print "# This file is generated automatically from the data in the public-domain" + print "# NIST/IERS format leap-seconds.list file, which can be copied from" + print "# <https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list>" +- print "# or, in a variant with different comments, from" ++ print "# or via a less-secure protocol and with different comments and" ++ print "# less volatile last-modified and expiration timestamps, from" + print "# <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>." + print "# For more about leap-seconds.list, please see" + print "# The NTP Timescale and Leap Seconds" +@@ -125,7 +126,13 @@ + epoch_minus_NTP = ((1970 - 1900) * 365 + 17) * 24 * 60 * 60 + + print "" +- print "# POSIX timestamps for the data in this file:" ++ print "# Here are POSIX timestamps for the data in this file." ++ print "# \"#updated\" gives the last time the leap seconds data changed" ++ print "# or, if this file was derived from the IERS leap-seconds.list," ++ print "# the last time that file changed in any way." ++ print "# \"#expires\" gives the first time this file might be wrong;" ++ print "# if this file was derived from the IERS leap-seconds.list," ++ print "# this is typically a bit less than one year after \"updated\"." + if (updated) { + sstamp_to_ymdhMs(updated, ss_NTP) + printf "#updated %d (%.4d-%.2d-%.2d %.2d:%.2d:%.2d UTC)\n", \ +--- contrib/tzdata/northamerica.orig ++++ contrib/tzdata/northamerica +@@ -6,9 +6,9 @@ + # also includes Central America and the Caribbean + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (1999-03-22): + # A reliable and entertaining source about time zones is +@@ -1218,6 +1218,16 @@ + # _Los Angeles Times_ (1998-11-10), A1, A10; it cites + # Jimmy Skaggs, _The Great Guano Rush_ (1994). + ++# From Rob van Gent (2025-07-23): ++# Another useful source for historical time zone information appears to be ++# a series of circulars with the title "Standard Time Throughout the World" ++# issued between 1925 and 1950 by the U.S. Bureau of Standards. ++# I found the following issues online: ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular280.pdf (1925) ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular399.pdf (1932) ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular406.pdf (1935) ++# https://nvlpubs.nist.gov/nistpubs/Legacy/circ/nbscircular496.pdf (1950) ++ + ################################################################################ + + +@@ -1947,6 +1957,56 @@ + # https://searcharchives.vancouver.ca/daylight-saving-1918-starts-again-july-7-1941-start-d-s-sept-27-end-of-d-s-1941 + # We have no further details, so omit them for now. + ++# From Arthur David Olson (2026-03-02): ++# B. C. Gov News: “Adopting permanent daylight saving time: ‘Spring forward’ ++# on March 8 will be the last time change, ending twice-yearly clock changes.” ++# https://news.gov.bc.ca/releases/2026AG0013-000209 ++# ++# From Paul Eggert (2026-03-07): ++# The law says that 21 hours after the usual 2026-03-08 02:00 switch from ++# PST to PDT, the next day inaugurates the new standard time Pacific Time, ++# i.e., just one clock change but two name changes separated by 21 hours. ++# PT, the obvious abbreviation for Pacific Time, is one letter too short ++# to conform to TZDB’s (and POSIX’s) [-+[:alnum:]]{3,6} requirements. ++# I asked the BC government for advice, with no response. For now, do this: ++# 1. As a temporary hack, pretend that the BC law takes effect ++# not on 2026-03-09 at 00:00, but on 2026-11-01 at 02:00. ++# This pretense works around a limitation in CLDR v48.2 (2026-03-17), ++# which would otherwise say the interval uses “Pacific Standard Time”. ++# (Below, this temporary hack is marked “Temporary hack; see above.”) ++# Strictly speaking this hack is incorrect since the interval uses ++# standard time, but it does have the right UT offset and it ++# works around the CLDR limitation. We should be able to remove ++# the temporary hack after CLDR is fixed. ++# 2. After the BC law takes effect, model the time as MST sans DST. ++# We can change this later if another conforming non-numeric abbreviation ++# for Pacific Time becomes more popular. Possibilities include: ++# MST - the most compatible with existing software and practice, ++# and already used in parts of BC and in Yukon ++# PDT - almost as software-friendly, but confusing because it implies ++# it is DST and is paired with PST, whereas PT is standard time ++# PST - straightforward but even more confusing, ++# and will likely break much software that assumes PST is -08 ++# -07 - accurate and clear in itself, but makes BC look odd vs neighbors ++# CPT, CPST - for Canadian Pacific (Standard) Time, ++# by analogy with AEST in Australia ++# P-T - conforming approximation to “PT” ++# PT+ - like P-T but suggesting one-hour advance over PST ++ ++# From Chris Walton (2026-03-15): ++# The Regional District of East Kootenay is planning to move to year-round ++# Mountain Standard Time (MST) on November 1, 2026.... ++# https://www.rdek.bc.ca/news/entry/rdek_board_moves_to_transition_to_year_round_mountain_standard_time ++# (2026-03-17): ++# The final decision East Kootenay made a few days ago may turn out not to ++# be final after all. They are going to reopen the debate next month! ++# https://www.cbc.ca/news/canada/british-columbia/what-time-is-it-in-the-east-kootenay-debate-9.7132624 ++# From Paul Eggert (2026-03-17): ++# Mayor Steve Fairbairn of Elkford asked the question be called a second time, ++# saying, “Pardon the pun, but this is not a time-sensitive issue.” ++# For now, merely mention the potential change in these comments. ++# If it happens it would likely affect clocks starting 2027-03-14 at 02:00. ++ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S + Rule Vanc 1918 only - Apr 14 2:00 1:00 D + Rule Vanc 1918 only - Oct 27 2:00 0 S +@@ -1960,7 +2020,11 @@ + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Vancouver -8:12:28 - LMT 1884 + -8:00 Vanc P%sT 1987 +- -8:00 Canada P%sT ++ -8:00 Canada P%sT 2026 Mar 9 ++ # Temporary hack; see above. ++ -8:00 1:00 PDT 2026 Nov 1 02:00 ++ # End of temporary hack. ++ -7:00 - MST + Zone America/Dawson_Creek -8:00:56 - LMT 1884 + -8:00 Canada P%sT 1947 + -8:00 Vanc P%sT 1972 Aug 30 2:00 +@@ -2434,12 +2498,35 @@ + # on the same dates or with a difference of one day. + # So it may be easier to implement these changes as DST with rule CA + # during this whole period. +-# +-# From Paul Eggert (2024-08-18): +-# For now, maintain the slightly-different history for Baja California, ++ ++# From Alois Treindl (2025-07-29): ++# I did a quick newspaper archive research on https://hndm.iib.unam.mx/ ++# and found that Periódico Oficial del Estado de Baja California Norte ++# (1973-04-20) states clearly that DST was observed from last Sunday ++# in April to last Sunday in October.... I have a few more data from the ++# official bulletin for DST begin or end in Baja California 1964 1967 1969 ++# 1972 1973 (already sent) 1974 1975 1976 I do not know whether it is safe to ++# assume that it also applied in the years where I did not yet find proof. ++# The 1974 end of DST contains a reference to an Acuerdo of 1973-dec-20 which ++# I could not find.... One might assume that Baja California, which followed ++# US-CA in all these other yours, did the same. ++# ++# From Paul Eggert (2025-08-04): ++# Assume that Tijuana agreed with San Diego from 1953 through 1996, ++# as this agrees with Alois Treindl's data and with Shanks. ++# For now, keep the slightly-different 1948/1952 history for Baja California, + # as we have no information on whether 1948/1952 clocks in Tijuana followed + # the decrees or followed San Diego. + ++# From Mark Schapiro, writing in The Nation (2002-10-28): ++# https://www.thenation.com/article/archive/sowing-disaster/ ++# When Mexican clocks were turned back for daylight saving time in the spring, ++# the Zapotecs refused to make the adjustment, insisting that they live in ++# "God's time," not in what they derisively call "Fox time," referring to ++# President Vicente Fox in far-off Mexico City. ++# From Paul Eggert (2025-08-04): ++# Unfortunately we have no data to track this informal practice. ++ + # From Alan Perry (1996-02-15): + # A guy from our Mexico subsidiary finally found the Presidential Decree + # outlining the timezone changes in Mexico. +@@ -2705,7 +2792,7 @@ + # Chihuahua (near US border - western side) + # This includes the municipios of Janos, Ascensión, Juárez, Guadalupe, and + # Práxedis G Guerrero. +-# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf ++# https://gaceta.diputados.gob.mx/PDF/65/2022/nov/20221124-VII.pdf + Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u + -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 +@@ -2720,7 +2807,7 @@ + # Chihuahua (near US border - eastern side) + # This includes the municipios of Coyame del Sotol, Ojinaga, and Manuel + # Benavides. +-# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf ++# https://gaceta.diputados.gob.mx/PDF/65/2022/nov/20221124-VII.pdf + Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u + -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 +@@ -2817,9 +2904,7 @@ + -8:00 1:00 PDT 1951 Sep 30 2:00 + -8:00 - PST 1952 Apr 27 2:00 + -8:00 1:00 PDT 1952 Sep 28 2:00 +- -8:00 - PST 1954 +- -8:00 CA P%sT 1961 +- -8:00 - PST 1976 ++ -8:00 CA P%sT 1967 + -8:00 US P%sT 1996 + -8:00 Mexico P%sT 2001 + -8:00 US P%sT 2002 Feb 20 +--- contrib/tzdata/southamerica.orig ++++ contrib/tzdata/southamerica +@@ -4,9 +4,9 @@ + # 2009-05-17 by Arthur David Olson. + + # This file is by no means authoritative; if you think you know better, +-# go ahead and edit the file (and please send any changes to +-# tz@iana.org for general use in the future). For more, please see +-# the file CONTRIBUTING in the tz distribution. ++# go ahead and edit the file, and please send any changes to ++# the public mailing list tz@iana.org for general use in the future. ++# For more, please see the file CONTRIBUTING in the tz distribution. + + # From Paul Eggert (2016-12-05): + # +--- contrib/tzdata/theory.html.orig ++++ contrib/tzdata/theory.html +@@ -3,14 +3,16 @@ + <head> + <title>Theory and pragmatics of the tz code and data</title> + <meta charset="UTF-8"> ++ <meta name="viewport" content="width=device-width, initial-scale=1"> + <style> +- pre {margin-left: 2em; white-space: pre-wrap;} ++ dd {margin-left: 1.3rem;} ++ pre {margin-left: 1.3rem; overflow: auto;} ++ ul {padding-left: 1.3rem;} + </style> + </head> + + <body> + <h1>Theory and pragmatics of the <code><abbr>tz</abbr></code> code and data</h1> +- <h3>Outline</h3> + <nav> + <ul> + <li><a href="#scope">Scope of the <code><abbr>tz</abbr></code> +@@ -89,24 +91,25 @@ + href="https://en.wikipedia.org/wiki/POSIX">POSIX</a>, an international + standard for <a + href="https://en.wikipedia.org/wiki/Unix">UNIX</a>-like systems. +-As of this writing, the current edition of POSIX is POSIX.1-2024, +-which has been published but not yet in HTML form. +-Unlike its predecessor POSIX.1-2017 (<a +-href="https://pubs.opengroup.org/onlinepubs/9699919799/"> The Open +-Group Base Specifications Issue 7</a>, IEEE Std 1003.1-2017, 2018 +-Edition), POSIX.1-2024 requires support for the ++As of this writing, the current edition of POSIX is ++<a href="https://pubs.opengroup.org/onlinepubs/9799919799/">POSIX.1-2024</a> ++(The Open Group Base Specifications Issue 8, IEEE Std 1003.1-2024). ++Unlike its predecessors ++<a href="https://archive.org/details/POSIX.1-1988">POSIX.1-1988</a> through ++<a href="https://pubs.opengroup.org/onlinepubs/9699919799/">POSIX.1-2017</a>, ++POSIX.1-2024 requires support for the + <code><abbr>tz</abbr></code> database, which has a + model for describing civil time that is more complex than the +-standard and daylight saving times required by POSIX.1-2017. ++standard and daylight saving times required by earlier POSIX editions. + A <code><abbr>tz</abbr></code> timezone corresponds to a ruleset that can + have more than two changes per year, these changes need not merely + flip back and forth between two alternatives, and the rules themselves + can change at times. + Whether and when a timezone changes its clock, +-and even the timezone's notional base offset from <abbr>UTC</abbr>, ++and even the timezone’s notional base offset from <abbr>UTC</abbr>, + are variable. +-It does not always make sense to talk about a timezone's +-"base offset", which is not necessarily a single number. ++It does not always make sense to talk about a timezone’s ++“base offset”, which is not necessarily a single number. + </p> + + </section> +@@ -118,16 +121,16 @@ + Inexperienced users are not expected to select these names unaided. + Distributors should provide documentation and/or a simple selection + interface that explains each name via a map or via descriptive text like +-"Czech Republic" instead of the timezone name "<code>Europe/Prague</code>". ++“Czech Republic” instead of the timezone name “<code>Europe/Prague</code>”. + If geolocation information is available, a selection interface can + locate the user on a timezone map or prioritize names that are + geographically close. For an example selection interface, see the + <code>tzselect</code> program in the <code><abbr>tz</abbr></code> code. +-Unicode's <a href="https://cldr.unicode.org">Common Locale Data ++Unicode’s <a href="https://cldr.unicode.org">Common Locale Data + Repository (<abbr>CLDR</abbr>)</a> + contains data that may be useful for other selection + interfaces; it maps timezone names like <code>Europe/Prague</code> to +-locale-dependent strings like "Prague", "Praha", "Прага", and "布拉格". ++locale-dependent strings like “Prague”, “Praha”, “Прага”, and “布拉格”. + </p> + + <p> +@@ -142,13 +145,13 @@ + civil time. + </li> + <li> +- Indicate to experts where the timezone's clocks typically are. ++ Indicate to experts where the timezone’s clocks typically are. + </li> + <li> + Be robust in the presence of political changes. + For example, names are typically not tied to countries, to avoid + incompatibilities when countries change their name (e.g., +- Swaziland→Eswatini) or when locations change countries (e.g., Hong ++ Swaziland→Eswatini) or when locations change countries (e.g., Hong + Kong from UK colony to China). + There is no requirement that every country or national + capital must have a timezone name. +@@ -166,11 +169,11 @@ + <var>AREA</var><code>/</code><var>LOCATION</var>, where + <var>AREA</var> is a continent or ocean, and + <var>LOCATION</var> is a specific location within the area. +-North and South America share the same area, '<code>America</code>'. +-Typical names are '<code>Africa/Cairo</code>', +-'<code>America/New_York</code>', and '<code>Pacific/Honolulu</code>'. ++North and South America share the same area, <code>America</code>. ++Typical names are <code>Africa/Cairo</code>, ++<code>America/New_York</code>, and <code>Pacific/Honolulu</code>. + Some names are further qualified to help avoid confusion; for example, +-'<code>America/Indiana/Petersburg</code>' distinguishes Petersburg, ++<code>America/Indiana/Petersburg</code> distinguishes Petersburg, + Indiana from other Petersburgs in America. + </p> + +@@ -183,25 +186,25 @@ + <ul> + <li> + Use only valid POSIX file name components (i.e., the parts of +- names other than '<code>/</code>'). +- Do not use the file name components '<code>.</code>' and +- '<code>..</code>'. ++ names other than "<code>/</code>"). ++ Do not use the file name components "<code>.</code>" and ++ "<code>..</code>". + Within a file name component, use only <a + href="https://en.wikipedia.org/wiki/ASCII">ASCII</a> letters, +- '<code>.</code>', '<code>-</code>' and '<code>_</code>'. ++ "<code>.</code>", "<code>-</code>" and "<code>_</code>". + Do not use digits, as that might create an ambiguity with <a +- href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03">POSIX's proleptic +- <code>TZ</code> strings</a>. ++ href="https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap08.html#tag_08_03">POSIX’s ++ proleptic <code>TZ</code> strings</a>. + A file name component must not exceed 14 characters or start with +- '<code>-</code>'. ++ "<code>-</code>". + E.g., prefer <code>America/Noronha</code> to + <code>America/Fernando_de_Noronha</code>. + Exceptions: see the discussion of legacy names below. + </li> + <li> +- A name must not be empty, or contain '<code>//</code>', or +- start or end with '<code>/</code>'. +- Also, a name must not be '<code>Etc/Unknown</code>', as ++ A name must not be empty, or contain "<code>//</code>", or ++ start or end with "<code>/</code>". ++ Also, a name must not be "<code>Etc/Unknown</code>", as + <abbr>CLDR</abbr> uses that string for an unknown or invalid timezone. + </li> + <li> +@@ -213,7 +216,7 @@ + <li> + If one name <var>A</var> is an initial prefix of another + name <var>AB</var> (ignoring case), then <var>B</var> must not +- start with '<code>/</code>', as a regular file cannot have the ++ start with "<code>/</code>", as a regular file cannot have the + same name as a directory in POSIX. + For example, <code>America/New_York</code> precludes + <code>America/New_York/Bronx</code>. +@@ -280,8 +283,8 @@ + <code>Atlantic/Canaries</code>. + </li> + <li> +- Omit common suffixes like '<code>_Islands</code>' and +- '<code>_City</code>', unless that would lead to ambiguity. ++ Omit common suffixes like "<code>_Islands</code>" and ++ "<code>_City</code>", unless that would lead to ambiguity. + E.g., prefer <code>America/Cayman</code> to + <code>America/Cayman_Islands</code> and + <code>America/Guatemala</code> to +@@ -292,10 +295,10 @@ + country of Mexico has several time zones</a>. + </li> + <li> +- Use '<code>_</code>' to represent a space. ++ Use "<code>_</code>" to represent a space. + </li> + <li> +- Omit '<code>.</code>' from abbreviations in names. ++ Omit "<code>.</code>" from abbreviations in names. + E.g., prefer <code>Atlantic/St_Helena</code> to + <code>Atlantic/St._Helena</code>. + </li> +@@ -303,15 +306,15 @@ + Do not change established names if they only marginally violate + the above guidelines. + For example, do not change the existing name <code>Europe/Rome</code> to +- <code>Europe/Milan</code> merely because Milan's population has grown +- to be somewhat greater than Rome's. ++ <code>Europe/Milan</code> merely because Milan’s population has grown ++ to be somewhat greater than Rome’s. + </li> + <li> + If a name is changed, put its old spelling in the +- '<code>backward</code>' file as a link to the new spelling. ++ "<code>backward</code>" file as a link to the new spelling. + This means old spellings will continue to work. + Ordinarily a name change should occur only in the rare case when +- a location's consensus English-language spelling changes; for example, ++ a location’s consensus English-language spelling changes; for example, + in 2008 <code>Asia/Calcutta</code> was renamed to <code>Asia/Kolkata</code> + due to long-time widespread use of the new city name instead of the old. + </li> +@@ -327,11 +330,11 @@ + <ul> + <li> + Older versions of this package used a different naming scheme. +-See the file '<code>backward</code>' for most of these older names +-(e.g., '<code>US/Eastern</code>' instead of '<code>America/New_York</code>'). ++See the file "<code>backward</code>" for most of these older names ++(e.g., <code>US/Eastern</code> instead of <code>America/New_York</code>). + The other old-fashioned names still supported are +-'<code>WET</code>', '<code>CET</code>', '<code>MET</code>', and +-'<code>EET</code>' (see the file '<code>europe</code>'). ++<code>WET</code>, <code>CET</code>, <code>MET</code>, and ++<code>EET</code> (see the file "<code>europe</code>"). + </li> + + <li> +@@ -339,13 +342,13 @@ + incompatible with the first guideline of location names, but which are + still supported. + These legacy names are mostly defined in the file +-'<code>etcetera</code>'. +-Also, the file '<code>backward</code>' defines the legacy names +-'<code>Etc/GMT0</code>', '<code>Etc/GMT-0</code>', '<code>Etc/GMT+0</code>', +-'<code>GMT0</code>', '<code>GMT-0</code>' and '<code>GMT+0</code>', +-and the file '<code>northamerica</code>' defines the legacy names +-'<code>EST5EDT</code>', '<code>CST6CDT</code>', +-'<code>MST7MDT</code>', and '<code>PST8PDT</code>'. ++"<code>etcetera</code>". ++Also, the file "<code>backward</code>" defines the legacy names ++<code>Etc/GMT0</code>, <code>Etc/GMT-0</code>, <code>Etc/GMT+0</code>, ++<code>GMT0</code>, <code>GMT-0</code> and <code>GMT+0</code>, ++and the file "<code>northamerica</code>" defines the legacy names ++<code>EST5EDT</code>, <code>CST6CDT</code>, ++<code>MST7MDT</code>, and <code>PST8PDT</code>. + </li> + + <li> +@@ -365,11 +368,11 @@ + to name timezones. + It is intended to be an exhaustive list of names for geographic + regions as described above; this is a subset of the timezones in the data. +-Although a <code>zone1970.tab</code> location's ++Although a <code>zone1970.tab</code> location’s + <a href="https://en.wikipedia.org/wiki/Longitude">longitude</a> + corresponds to + its <a href="https://en.wikipedia.org/wiki/Local_mean_time">local mean +-time (<abbr>LMT</abbr>)</a> offset with one hour for every 15° ++time (<abbr>LMT</abbr>)</a> offset with one hour for every 15° + east longitude, this relationship is not exact. + The backward-compatibility file <code>zone.tab</code> is similar + but conforms to the older-version guidelines related to <abbr>ISO</abbr> 3166-1; +@@ -395,7 +398,7 @@ + like <code><+08>-8</code>; + no other source file other than <code>backward</code> + contains links to its zones. +-One of <code>etcetera</code>'s names is <code>Etc/UTC</code>, ++One of <code>etcetera</code>’s names is <code>Etc/UTC</code>, + used by functions like <code>gmtime</code> to obtain leap + second information on platforms that support leap seconds. + Another <code>etcetera</code> name, <code>GMT</code>, +@@ -407,7 +410,7 @@ + <h2 id="abbreviations">Time zone abbreviations</h2> + <p> + When this package is installed, it generates time zone abbreviations +-like '<code>EST</code>' to be compatible with human tradition and POSIX. ++like <code>EST</code> to be compatible with human tradition and POSIX. + Here are the general guidelines used for choosing time zone abbreviations, + in decreasing order of importance: + </p> +@@ -415,25 +418,24 @@ + <ul> + <li> + Use three to six characters that are ASCII alphanumerics or +- '<code>+</code>' or '<code>-</code>'. ++ "<code>+</code>" or "<code>-</code>". + Previous editions of this database also used characters like +- space and '<code>?</code>', but these characters have a ++ space and "<code>?</code>", but these characters have a + special meaning to the + <a href="https://en.wikipedia.org/wiki/Unix_shell">UNIX shell</a> + and cause commands like +- '<code><a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set">set</a> +- `<a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html">date</a>`</code>' ++ "<code><a href="https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#set">set</a> ++ `<a href="https://pubs.opengroup.org/onlinepubs/9799919799/utilities/date.html">date</a>`</code>" + to have unexpected effects. + Previous editions of this guideline required upper-case letters, but the + Congressman who introduced + <a href="https://en.wikipedia.org/wiki/Chamorro_Time_Zone">Chamorro +- Standard Time</a> preferred "ChST", so lower-case letters are now +- allowed. +- Also, POSIX from 2001 on relaxed the rule to allow '<code>-</code>', +- '<code>+</code>', and alphanumeric characters from the portable ++ Standard Time</a> preferred “ChST”, so lower-case letters are now allowed. ++ Also, POSIX from 2001 on relaxed the rule to allow "<code>-</code>", ++ "<code>+</code>", and alphanumeric characters from the portable + character set in the current locale. +- In practice ASCII alphanumerics and '<code>+</code>' and +- '<code>-</code>' are safe in all locales. ++ In practice ASCII alphanumerics and "<code>+</code>" and ++ "<code>-</code>" are safe in all locales. + + <p> + In other words, in the C locale the POSIX extended regular +@@ -445,10 +447,10 @@ + </li> + <li> + Use abbreviations that are in common use among English-speakers, +- e.g., 'EST' for Eastern Standard Time in North America. ++ e.g., “EST” for Eastern Standard Time in North America. + We assume that applications translate them to other languages + as part of the normal localization process; for example, +- a French application might translate 'EST' to 'HNE'. ++ a French application might translate “EST” to “HNE”. + + <p> + <small>These abbreviations (for standard/daylight/etc. time) are: +@@ -483,7 +485,7 @@ + NST/NDT/NWT/NPT/NDDT Newfoundland, + NST/NDT/NWT/NPT Nome, + NZMT/NZST New Zealand through 1945, +- NZST/NZDT New Zealand 1946–present, ++ NZST/NZDT New Zealand 1946–present, + PKT/PKST Pakistan, + PST/PDT/PWT/PPT Pacific, + PST/PDT Philippine, +@@ -500,12 +502,12 @@ + </li> + <li> + <p> +- For times taken from a city's longitude, use the ++ For times taken from a city’s longitude, use the + traditional <var>x</var>MT notation. +- The only abbreviation like this in current use is '<abbr>GMT</abbr>'. ++ The only abbreviation like this in current use is <abbr>GMT</abbr>. + The others are for timestamps before 1960, + except that Monrovia Mean Time persisted until 1972. +- Typically, numeric abbreviations (e.g., '<code>-</code>004430' for ++ Typically, numeric abbreviations (e.g., <code>-</code>004430 for + MMT) would cause trouble here, as the numeric strings would exceed + the POSIX length limit. + </p> +@@ -546,39 +548,39 @@ + <small>A few abbreviations also follow the pattern that + <abbr>GMT</abbr>/<abbr>BST</abbr> established for time in the UK. + They are: +- BMT/BST for Bermuda 1890–1930, ++ BMT/BST for Bermuda 1890–1930, + CMT/BST for Calamarca Mean Time and Bolivian Summer Time +- 1890–1932, ++ 1890–1932, + DMT/IST for Dublin/Dunsink Mean Time and Irish Summer Time +- 1880–1916, +- MMT/MST/MDST for Moscow 1880–1919, and +- RMT/LST for Riga Mean Time and Latvian Summer time 1880–1926. ++ 1880–1916, ++ MMT/MST/MDST for Moscow 1880–1919, and ++ RMT/LST for Riga Mean Time and Latvian Summer time 1880–1926. + </small> + </p> + </li> + <li> +- Use '<abbr>LMT</abbr>' for local mean time of locations before the +- introduction of standard time; see "<a href="#scope">Scope of the +- <code><abbr>tz</abbr></code> database</a>". ++ Use “<abbr>LMT</abbr>” for local mean time of locations before the ++ introduction of standard time; see “<a href="#scope">Scope of the ++ <code><abbr>tz</abbr></code> database</a>”. + </li> + <li> + If there is no common English abbreviation, use numeric offsets like + <code>-</code>05 and <code>+</code>0530 that are generated +- by <code>zic</code>'s <code>%z</code> notation. ++ by <code>zic</code>’s <code>%z</code> notation. + </li> + <li> + Use current abbreviations for older timestamps to avoid confusion. + For example, in 1910 a common English abbreviation for time +- in central Europe was 'MEZ' (short for both "Middle European +- Zone" and for "Mitteleuropäische Zeit" in German). +- Nowadays 'CET' ("Central European Time") is more common in +- English, and the database uses 'CET' even for circa-1910 ++ in central Europe was “MEZ” (short for both “Middle European ++ Zone” and for “Mitteleuropäische Zeit” in German). ++ Nowadays “CET” (“Central European Time”) is more common in ++ English, and the database uses “CET” even for circa-1910 + timestamps as this is less confusing for modern users and avoids +- the need for determining when 'CET' supplanted 'MEZ' in common ++ the need for determining when “CET” supplanted “MEZ” in common + usage. + </li> + <li> +- Use a consistent style in a timezone's history. ++ Use a consistent style in a timezone’s history. + For example, if a history tends to use numeric + abbreviations and a particular entry could go either way, use a + numeric abbreviation. +@@ -586,13 +588,13 @@ + <li> + Use + <a href="https://en.wikipedia.org/wiki/Universal_Time">Universal Time</a> +- (<abbr>UT</abbr>) (with time zone abbreviation '<code>-</code>00') for ++ (<abbr>UT</abbr>) (with time zone abbreviation <code>-</code>00) for + locations while uninhabited. +- The leading '<code>-</code>' is a flag that the <abbr>UT</abbr> offset is in ++ The leading "<code>-</code>" is a flag that the <abbr>UT</abbr> offset is in + some sense undefined; this notation is derived + from <a href="https://www.rfc-editor.org/rfc/rfc3339">Internet + <abbr title="Request For Comments">RFC</abbr> 3339</a>. +- (The abbreviation 'Z' that ++ (The abbreviation Z that + <a href="https://www.rfc-editor.org/rfc/rfc9557">Internet + <abbr>RFC</abbr> 9557</a> uses for this concept + would violate the POSIX requirement +@@ -602,11 +604,11 @@ + + <p> + Application writers should note that these abbreviations are ambiguous +-in practice: e.g., 'CST' means one thing in China and something else +-in North America, and 'IST' can refer to time in India, Ireland or ++in practice: e.g., CST means one thing in China and something else ++in North America, and IST can refer to time in India, Ireland or + Israel. + To avoid ambiguity, use numeric <abbr>UT</abbr> offsets like +-'<code>-</code>0600' instead of time zone abbreviations like 'CST'. ++<code>-</code>0600 instead of time zone abbreviations like CST. + </p> + </section> + +@@ -617,7 +619,7 @@ + surely has errors. + Corrections are welcome and encouraged; see the file <code>CONTRIBUTING</code>. + Users requiring authoritative data should consult national standards +-bodies and the references cited in the database's comments. ++bodies and the references cited in the database’s comments. + </p> + + <p> +@@ -639,7 +641,7 @@ + clocks actually behaved; the vast majority of the necessary + information was lost or never recorded. + Thousands more timezones would be needed if +- the <code><abbr>tz</abbr></code> database's scope were extended to ++ the <code><abbr>tz</abbr></code> database’s scope were extended to + cover even just the known or guessed history of standard time; for + example, the current single entry for France would need to split + into dozens of entries, perhaps hundreds. +@@ -648,14 +650,14 @@ + should be observed. + In her 2015 book + <cite><a +- href="https://www.hup.harvard.edu/catalog.php?isbn=9780674286146">The +- Global Transformation of Time, 1870–1950</a></cite>, ++ href="https://www.hup.harvard.edu/books/9780674286146">The ++ Global Transformation of Time, 1870–1950</a></cite>, + Vanessa Ogle writes +- "Outside of Europe and North America there was no system of time ++ “Outside of Europe and North America there was no system of time + zones at all, often not even a stable landscape of mean times, +- prior to the middle decades of the twentieth century". ++ prior to the middle decades of the twentieth century”. + See: Timothy Shenk, <a +-href="https://www.dissentmagazine.org/blog/booked-a-global-history-of-time-vanessa-ogle">Booked: ++href="https://dissentmagazine.org/blog/booked-a-global-history-of-time-vanessa-ogle/">Booked: + A Global History of Time</a>. <cite>Dissent</cite> 2015-12-17. + </li> + <li> +@@ -671,8 +673,8 @@ + For the UK the <code><abbr>tz</abbr></code> database relies on + years of first-class work done by + Joseph Myers and others; see +- "<a href="https://www.polyomino.org.uk/british-time/">History of +- legal time in Britain</a>". ++ “<a href="https://www.polyomino.org.uk/british-time/">History of ++ legal time in Britain</a>”. + Other countries are not done nearly as well. + </li> + <li> +@@ -697,13 +699,13 @@ + entries are often accurate for only a small subset of that region. + For example, <code>Europe/London</code> stands for the United + Kingdom, but its pre-1847 times are valid only for locations that +- have London's exact meridian, and its 1847 transition ++ have London’s exact meridian, and its 1847 transition + to <abbr>GMT</abbr> is known to be valid only for the L&NW and + the Caledonian railways. + </li> + <li> + The <code><abbr>tz</abbr></code> database does not record the +- earliest time for which a timezone's ++ earliest time for which a timezone’s + data entries are thereafter valid for every location in the region. + For example, <code>Europe/London</code> is valid for all locations + in its region after <abbr>GMT</abbr> was made the standard time, +@@ -714,7 +716,7 @@ + </li> + <li> + The <code><abbr>tz</abbr></code> database does not record a +- region's boundaries, and in many cases the boundaries are not known. ++ region’s boundaries, and in many cases the boundaries are not known. + For example, the timezone + <code>America/Kentucky/Louisville</code> represents a region + around the city of Louisville, the boundaries of which are +@@ -747,7 +749,7 @@ + than what the <code><abbr>tz</abbr></code> code can handle. + For example, from 1880 to 1916 clocks in Ireland observed Dublin Mean + Time (estimated to be <abbr>UT</abbr> +- −00:25:21.1); although the <code><abbr>tz</abbr></code> ++ −00:25:21.1); although the <code><abbr>tz</abbr></code> + source data can represent the .1 second, TZif files and the code cannot. + In practice these old specifications were rarely if ever + implemented to subsecond precision. +@@ -787,9 +789,9 @@ + non-hour-based system at night. + And even today, some local practices diverge from the Gregorian + calendar with 24-hour days. These divergences range from +- relatively minor, such as Japanese bars giving times like "24:30" for the ++ relatively minor, such as Japanese bars giving times like 24:30 for the + wee hours of the morning, to more-significant differences such as <a +- href="https://theworld.org/stories/2015-01-30/if-you-have-meeting-ethiopia-you-better-double-check-time">the ++ href="https://theworld.org/stories/2015/01/30/ethiopian-time">the + east African practice of starting the day at dawn</a>, renumbering + the Western 06:00 to be 12:00. These practices are largely outside + the scope of the <code><abbr>tz</abbr></code> code and data, which +@@ -825,16 +827,16 @@ + <li> + Civil time was not based on atomic time before 1972, and we do not + know the history of +- <a href="https://en.wikipedia.org/wiki/Earth's_rotation">earth's ++ <a href="https://en.wikipedia.org/wiki/Earth's_rotation">earth’s + rotation</a> accurately enough to map <a + href="https://en.wikipedia.org/wiki/International_System_of_Units"><abbr + title="International System of Units">SI</abbr></a> seconds to + historical <a href="https://en.wikipedia.org/wiki/Solar_time">solar time</a> + to more than about one-hour accuracy. +- See: Stephenson FR, Morrison LV, Hohenkerk CY. +- <a href="https://dx.doi.org/10.1098/rspa.2016.0404">Measurement of +- the Earth's rotation: 720 BC to AD 2015</a>. +- <cite>Proc Royal Soc A</cite>. 2016;472:20160404. ++ See: Morrison LV, Stephenson FR, Hohenkerk CY, Zawilski M. ++ <a href="https://doi.org/10.1098/rspa.2020.0776">Addendum 2020 ++ to ‘Measurement of the Earth’s rotation: 720 BC to AD 2015’</a>. ++ <cite>Proc Royal Soc A</cite>. 2021;477:20200776. + Also see: Espenak F. <a + href="https://eclipse.gsfc.nasa.gov/SEhelp/uncertainty2004.html">Uncertainty + in Delta T (ΔT)</a>. +@@ -843,7 +845,7 @@ + The relationship between POSIX time (that is, <abbr>UTC</abbr> but + ignoring <a href="https://en.wikipedia.org/wiki/Leap_second">leap + seconds</a>) and <abbr>UTC</abbr> is not agreed upon. +- This affects time stamps during the leap second era (1972–2035). ++ This affects time stamps during the leap second era (1972–2035). + Although the POSIX + clock officially stops during an inserted leap second, at least one + proposed standard has it jumping back a second instead; and in +@@ -862,12 +864,12 @@ + + <p> + In short, many, perhaps most, of the <code><abbr>tz</abbr></code> +-database's pre-1970 and future timestamps are either wrong or ++database’s pre-1970 and future timestamps are either wrong or + misleading. + Any attempt to pass the + <code><abbr>tz</abbr></code> database off as the definition of time + should be unacceptable to anybody who cares about the facts. +-In particular, the <code><abbr>tz</abbr></code> database's ++In particular, the <code><abbr>tz</abbr></code> database’s + <abbr>LMT</abbr> offsets should not be considered meaningful, and + should not prompt creation of timezones + merely because two locations +@@ -886,7 +888,7 @@ + primary use of this package is to update obsolete time-related files. + To do this, you may need to compile the time zone compiler + <code>zic</code> supplied with this package instead of using the +-system <code>zic</code>, since the format of <code>zic</code>'s ++system <code>zic</code>, since the format of <code>zic</code>’s + input is occasionally extended, and a platform may still be shipping + an older <code>zic</code>. + </p> +@@ -914,7 +916,8 @@ + + <h3 id="POSIX.1-2017">POSIX.1-2017 properties and limitations</h3> + <p> +-Some platforms support only the features required by POSIX.1-2017, ++Some platforms support only the features required by POSIX.1-2017 ++and earlier editions, + and have not yet upgraded to POSIX.1-2024. + Code intended to be portable to these platforms must deal + with problems that were fixed in later POSIX editions. +@@ -956,14 +959,14 @@ + are 3 or more characters specifying the standard + and daylight saving time (<abbr>DST</abbr>) zone abbreviations. + Starting with POSIX.1-2001, <var>std</var> and <var>dst</var> +- may also be in a quoted form like '<code><+09></code>'; ++ may also be quoted in angle brackets, like <code><+09></code>; + this allows "<code>+</code>" and "<code>-</code>" in the names. + </dd> + <dt><var>offset</var></dt><dd> + is of the form +- '<code>[±]<var>hh</var>:[<var>mm</var>[:<var>ss</var>]]</code>' ++ <code>[±]<var>hh</var>:[<var>mm</var>[:<var>ss</var>]]</code> + and specifies the offset west of <abbr>UT</abbr>. +- '<var>hh</var>' may be a single digit; ++ <var>hh</var> may be a single digit; + 0≤<var>hh</var>≤24. + The default <abbr>DST</abbr> offset is one hour ahead of + standard time. +@@ -976,10 +979,10 @@ + </dd> + <dt><var>time</var></dt><dd> + takes the form +- '<var>hh</var><code>:</code>[<var>mm</var>[<code>:</code><var>ss</var>]]' ++ <var>hh</var><code>:</code>[<var>mm</var>[<code>:</code><var>ss</var>]] + and defaults to 02:00. + This is the same format as the offset, except that a +- leading '<code>+</code>' or '<code>-</code>' is not allowed. ++ leading "<code>+</code>" or "<code>-</code>" is not allowed. + </dd> + <dt><var>date</var></dt><dd> + takes one of the following forms: +@@ -996,7 +999,7 @@ + for the <var>d</var>th day of week <var>n</var> of + month <var>m</var> of the year, where week 1 is the first + week in which day <var>d</var> appears, and +- '<code>5</code>' stands for the last week in which ++ "<code>5</code>" stands for the last week in which + day <var>d</var> appears (which may be either the 4th or + 5th week). + Typically, this is the only useful form; the <var>n</var> +@@ -1011,8 +1014,8 @@ + Zealand after 2007. + It says that standard time (<abbr>NZST</abbr>) is 12 hours ahead + of <abbr>UT</abbr>, and that daylight saving time +- (<abbr>NZDT</abbr>) is observed from September's last Sunday at +- 02:00 until April's first Sunday at 03:00: ++ (<abbr>NZDT</abbr>) is observed from September’s last Sunday at ++ 02:00 until April’s first Sunday at 03:00: + </p> + + <pre><code>TZ='NZST-12NZDT,M9.5.0,M4.1.0/3'</code></pre> +@@ -1048,11 +1051,11 @@ + Earlier POSIX editions lack this requirement. + </li> + <li> +- DST transition times can range from −167:59:59 ++ DST transition times can range from −167:59:59 + to 167:59:59 instead of merely from 00:00:00 to 24:59:59. + This allows for proleptic TZ strings + like <code>"<-02>2<-01>,M3.5.0/-1,M10.5.0/0"</code> +- where the transition time −1:00 means 23:00 the previous day. ++ where the transition time −1:00 means 23:00 the previous day. + </li> + </ul> + <p> +@@ -1065,14 +1068,14 @@ + </li> + <li> + In POSIX, there is no tamper-proof way for a process to learn the +- system's best idea of local (wall clock) time. ++ system’s best idea of local (wall clock) time. + This is important for applications that an administrator wants +- used only at certain times – without regard to whether the ++ used only at certain times – without regard to whether the + user has fiddled the + <code>TZ</code> environment variable. +- While an administrator can "do everything in <abbr>UT</abbr>" to ++ While an administrator can “do everything in <abbr>UT</abbr>” to + get around the problem, doing so is inconvenient and precludes +- handling daylight saving time shifts – as might be required to ++ handling daylight saving time shifts – as might be required to + limit phone calls to off-peak hours. + </li> + <li> +@@ -1081,8 +1084,7 @@ + </li> + <li> + POSIX does not define the <abbr>DST</abbr> transitions +- for <code>TZ</code> values like +- "<code>EST5EDT</code>". ++ for settings like <code>TZ='EST5EDT'</code>. + Traditionally the current <abbr>US</abbr> <abbr>DST</abbr> rules + were used to interpret such values, but this meant that the + <abbr>US</abbr> <abbr>DST</abbr> rules were compiled into each +@@ -1124,9 +1126,9 @@ + If the <code>TZ</code> environment variable uses the geographical format, + it is used in generating + the name of a file from which time-related information is read. +- The file's format is <dfn><abbr>TZif</abbr></dfn>, ++ The file’s format is <dfn><abbr>TZif</abbr></dfn>, + a timezone information format that contains binary data; see +- <a href="https://www.rfc-editor.org/rfc/9636">Internet ++ <a href="https://www.rfc-editor.org/rfc/rfc9636">Internet + <abbr>RFC</abbr> 9636</a>. + The daylight saving time rules to be used for a + particular timezone are encoded in the +@@ -1138,18 +1140,18 @@ + <p> + When the <code><abbr>tz</abbr></code> code was developed in the 1980s, + it was recognized that allowing the <code>TZ</code> environment +- variable to take on values such as '<code>America/New_York</code>' +- might cause "old" programs (that expect <code>TZ</code> to have a ++ variable to take on values such as <code>America/New_York</code> ++ might cause old programs (that expect <code>TZ</code> to have a + certain format) to operate incorrectly; consideration was given to using + some other environment variable (for example, <code>TIMEZONE</code>) +- to hold the string used to generate the <abbr>TZif</abbr> file's name. ++ to hold the string used to generate the <abbr>TZif</abbr> file’s name. + In the end, however, it was decided to continue using + <code>TZ</code>: it is widely used for time zone purposes; + separately maintaining both <code>TZ</code> + and <code>TIMEZONE</code> seemed a nuisance; and systems where +- "new" forms of <code>TZ</code> might cause problems can simply +- use legacy <code>TZ</code> values such as "<code>EST5EDT</code>" which +- can be used by "new" programs as well as by "old" programs that ++ new forms of <code>TZ</code> might cause problems can simply ++ use legacy settings such as <code>TZ='EST5EDT'</code> which ++ can be used by new programs as well as by old programs that + assume pre-POSIX <code>TZ</code> values. + </p> + </li> +@@ -1192,20 +1194,20 @@ + The POSIX <code>tzname</code> variable does not suffice and is no + longer needed. + It is planned to be removed in a future edition of POSIX. +- To get a timestamp's time zone abbreviation, consult ++ To get a timestamp’s time zone abbreviation, consult + the <code>tm_zone</code> member if available; otherwise, +- use <code>strftime</code>'s <code>"%Z"</code> conversion ++ use <code>strftime</code>’s <code>"%Z"</code> conversion + specification. + </li> + <li> + The POSIX <code>daylight</code> and <code>timezone</code> + variables do not suffice and are no longer needed. + They are planned to be removed in a future edition of POSIX. +- To get a timestamp's <abbr>UT</abbr> offset, consult ++ To get a timestamp’s <abbr>UT</abbr> offset, consult + the <code>tm_gmtoff</code> member if available; otherwise, + subtract values returned by <code>localtime</code> + and <code>gmtime</code> using the rules of the Gregorian calendar, +- or use <code>strftime</code>'s <code>"%z"</code> conversion ++ or use <code>strftime</code>’s <code>"%z"</code> conversion + specification if a string like <code>"+0900"</code> suffices. + </li> + <li> +@@ -1230,9 +1232,9 @@ + <li> + The <a href="https://en.wikipedia.org/wiki/Version_7_Unix">7th Edition + UNIX</a> <code>timezone</code> function is not present in this +- package; it is impossible to reliably map <code>timezone</code>'s +- arguments (a "minutes west of <abbr>GMT</abbr>" value and a +- "daylight saving time in effect" flag) to a time zone ++ package; it is impossible to reliably map <code>timezone</code>’s ++ arguments (a “minutes west of <abbr>GMT</abbr>” value and a ++ “daylight saving time in effect” flag) to a time zone + abbreviation, and we refuse to guess. + Programs that in the past used the <code>timezone</code> function + may now examine <code>localtime(&clock)->tm_zone</code> +@@ -1262,7 +1264,7 @@ + The functions that are conditionally compiled + if <code>STD_INSPIRED</code> is nonzero should, at this point, be + looked on primarily as food for thought. +- They are not in any sense "standard compatible" – some are ++ They are not in any sense “standard compatible” – some are + not, in fact, specified in <em>any</em> standard. + They do, however, represent responses of various authors to + standardization proposals. +@@ -1293,11 +1295,11 @@ + <ul> + <li> + A set of timezone names as per +- "<a href="#naming">Timezone identifiers</a>" above. ++ “<a href="#naming">Timezone identifiers</a>” above. + </li> + <li> +- Library functions described in "<a href="#functions">Time and date +- functions</a>" above. ++ Library functions described in “<a href="#functions">Time and date ++ functions</a>” above. + </li> + <li> + The programs <code>tzselect</code>, <code>zdump</code>, +@@ -1319,7 +1321,7 @@ + </li> + <li> + The version number of the code and data, as the first line of +- the text file '<code>version</code>' in each release. ++ the text file "<code>version</code>" in each release. + </li> + </ul> + +@@ -1347,7 +1349,7 @@ + currently includes Chang Mai, Hanoi, and Phnom Penh, this is not part + of the stable interface and the timezone can split at any time. + If a calendar application records a future event in some location other +-than Bangkok by putting "<samp>Asia/Bangkok</samp>" in the event's record, ++than Bangkok by putting <samp>Asia/Bangkok</samp> in the event’s record, + the application should be robust in the presence of timezone splits + between now and the future time. + </p> +@@ -1381,7 +1383,7 @@ + <a href="https://www.ntp.org"><abbr title="Network Time Protocol">NTP</abbr></a> + software that adjusts the kernel clock. + However, kernel-clock twiddling approximates UTC only roughly, +-and systems needing more precise UTC can use this package's leap ++and systems needing more precise UTC can use this package’s leap + second support directly. + </p> + +@@ -1391,8 +1393,8 @@ + as opposed to POSIX <code>time_t</code> counts which exclude leap seconds. + This modified timescale is converted to <abbr>UTC</abbr> + at the same point that time zone and <abbr>DST</abbr> +-adjustments are applied – +-namely, at calls to <code>localtime</code> and analogous functions – ++adjustments are applied – ++namely, at calls to <code>localtime</code> and analogous functions – + and the process is driven by leap second information + stored in alternate versions of the <abbr>TZif</abbr> files. + Because a leap second adjustment may be needed even +@@ -1402,7 +1404,7 @@ + conventionally named <samp><abbr>Etc/UTC</abbr></samp> + (<samp><abbr>GMT</abbr></samp> in previous versions), + to see whether leap second corrections are needed. +-To convert an application's <code>time_t</code> timestamps to or from ++To convert an application’s <code>time_t</code> timestamps to or from + POSIX <code>time_t</code> timestamps (for use when, say, + embedding or interpreting timestamps in portable + <a href="https://en.wikipedia.org/wiki/Tar_(computing)"><code>tar</code></a> +@@ -1425,7 +1427,7 @@ + discard <samp>zoneinfo</samp> and rename <samp>zoneinfo-leaps</samp> + to <samp>zoneinfo</samp>. + Alternatively, you can install just one set of <abbr>TZif</abbr> files +-in the first place; see the <code>REDO</code> variable in this package's ++in the first place; see the <code>REDO</code> variable in this package’s + <a href="https://en.wikipedia.org/wiki/Makefile">makefile</a>. + </p> + </section> +@@ -1438,9 +1440,9 @@ + extended the time zone database further into the past. + An excellent resource in this area is Edward M. Reingold + and Nachum Dershowitz, <cite><a +-href="https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition">Calendrical ++href="https://www.cambridge.org/fr/universitypress/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition">Calendrical + Calculations: The Ultimate Edition</a></cite>, Cambridge University Press (2018). +-Other information and sources are given in the file '<code>calendars</code>' ++Other information and sources are given in the file "<code>calendars</code>" + in the <code><abbr>tz</abbr></code> distribution. + They sometimes disagree. + </p> +@@ -1450,20 +1452,20 @@ + <h2 id="planets">Time and time zones off Earth</h2> + <p> + The European Space Agency is <a +-href='https://www.esa.int/Applications/Navigation/Telling_time_on_the_Moon'>considering</a> ++href="https://www.esa.int/Applications/Satellite_navigation/Telling_time_on_the_Moon">considering</a> + the establishment of a reference timescale for the Moon, which has + days roughly equivalent to 29.5 Earth days, and where relativistic + effects cause clocks to tick slightly faster than on Earth. + Also, <abbr title="National Aeronautics and Space Administration">NASA</abbr> + has been <a +-href='https://www.whitehouse.gov/wp-content/uploads/2024/04/Celestial-Time-Standardization-Policy.pdf'>ordered</a> ++href="https://bidenwhitehouse.archives.gov/wp-content/uploads/2024/04/Celestial-Time-Standardization-Policy.pdf">ordered</a> + to consider the establishment of Coordinated Lunar Time (<abbr>LTC</abbr>). + It is not yet known whether the US and European efforts will result in + multiple timescales on the Moon. + </p> + + <p> +-Some people's work schedules have used ++Some people’s work schedules have used + <a href="https://en.wikipedia.org/wiki/Timekeeping_on_Mars">Mars time</a>. + Jet Propulsion Laboratory (JPL) coordinators kept Mars time on + and off during the +@@ -1473,7 +1475,7 @@ + Dozens of special Mars watches were built for JPL workers who kept + Mars time during the + <a href="https://en.wikipedia.org/wiki/Mars_Exploration_Rover">Mars +-Exploration Rovers (MER)</a> mission (2004–2018). ++Exploration Rovers (MER)</a> mission (2004–2018). + These timepieces looked like normal Seikos and Citizens but were adjusted + to use Mars seconds rather than terrestrial seconds, although + unfortunately the adjusted watches were unreliable and appear to have +@@ -1481,12 +1483,12 @@ + </p> + + <p> +-A Mars solar day is called a "sol" and has a mean period equal to ++A Mars solar day is called a “sol” and has a mean period equal to + about 24 hours 39 minutes 35.244 seconds in terrestrial time. + It is divided into a conventional 24-hour clock, so each Mars second + equals about 1.02749125 terrestrial seconds. +-(One MER worker noted, "If I am working Mars hours, and Mars hours are +-2.5% more than Earth hours, shouldn't I get an extra 2.5% pay raise?") ++(One MER worker noted, “If I am working Mars hours, and Mars hours are ++2.5% more than Earth hours, shouldn’t I get an extra 2.5% pay raise?”) + </p> + + <p> +@@ -1494,7 +1496,7 @@ + meridian</a> of Mars goes through the center of the crater + <a href="https://en.wikipedia.org/wiki/Airy-0">Airy-0</a>, named in + honor of the British astronomer who built the Greenwich telescope that +-defines Earth's prime meridian. ++defines Earth’s prime meridian. + Mean solar time on the Mars prime meridian is + called Mars Coordinated Time (<abbr>MTC</abbr>). + </p> +@@ -1502,13 +1504,13 @@ + <p> + Each landed mission on Mars has adopted a different reference for + solar timekeeping, so there is no real standard for Mars time zones. +-For example, the MER mission defined two time zones "Local +-Solar Time A" and "Local Solar Time B" for its two missions, each zone ++For example, the MER mission defined two time zones “Local ++Solar Time A” and “Local Solar Time B” for its two missions, each zone + designed so that its time equals local true solar time at + approximately the middle of the nominal mission. + The A and B zones differ enough so that an MER worker assigned to +-the A zone might suffer "Mars lag" when switching to work in the B zone. +-Such a "time zone" is not particularly suited for any application ++the A zone might suffer “Mars lag” when switching to work in the B zone. ++Such a “time zone” is not particularly suited for any application + other than the mission itself. + </p> + +@@ -1522,13 +1524,13 @@ + + <p> + In our solar system, Mars is the planet with time and calendar most +-like Earth's. ++like Earth’s. + On other planets, Sun-based time and calendars would work quite + differently. +-For example, although Mercury's ++For example, although Mercury’s + <a href="https://en.wikipedia.org/wiki/Rotation_period">sidereal + rotation period</a> is 58.646 Earth days, Mercury revolves around the +-Sun so rapidly that an observer on Mercury's equator would see a ++Sun so rapidly that an observer on Mercury’s equator would see a + sunrise only every 175.97 Earth days, i.e., a Mercury year is 0.5 of a + Mercury day. + Venus is more complicated, partly because its rotation is slightly +@@ -1554,8 +1556,8 @@ + <ul> + <li> + Michael Allison and Robert Schmunk, +- "<a href="https://www.giss.nasa.gov/tools/mars24/help/notes.html">Technical +- Notes on Mars Solar Time as Adopted by the Mars24 Sunclock</a>" ++ “<a href="https://www.giss.nasa.gov/tools/mars24/help/notes.html">Technical ++ Notes on Mars Solar Time as Adopted by the Mars24 Sunclock</a>” + (2020-03-08). + </li> + <li> +@@ -1565,28 +1567,33 @@ + </li> + <li> + Jia-Rui Chong, +- "<a href="https://www.latimes.com/archives/la-xpm-2004-jan-14-sci-marstime14-story.html">Workdays +- Fit for a Martian</a>", <cite>Los Angeles Times</cite> +- (2004-01-14), pp A1, A20–A21. ++ “<a href="https://www.latimes.com/archives/la-xpm-2004-jan-14-sci-marstime14-story.html">Workdays ++ Fit for a Martian</a>”, <cite>Los Angeles Times</cite> ++ (2004-01-14), pp A1, A20–A21. + </li> + <li> + Tom Chmielewski, +- "<a href="https://www.theatlantic.com/technology/archive/2015/02/jet-lag-is-worse-on-mars/386033/">Jet +- Lag Is Worse on Mars</a>", <cite>The Atlantic</cite> (2015-02-26) ++ “<a href="https://www.theatlantic.com/technology/archive/2015/02/jet-lag-is-worse-on-mars/386033/">Jet ++ Lag Is Worse on Mars</a>”, <cite>The Atlantic</cite> (2015-02-26) + </li> + <li> + Matt Williams, +- "<a href="https://www.universetoday.com/37481/days-of-the-planets/">How +- long is a day on the other planets of the solar system?</a>" ++ “<a href="https://www.universetoday.com/articles/days-of-the-planets">How ++ long is a day on the other planets of the solar system?</a>” + (2016-01-20). + </li> + </ul> + </section> + + <footer> +- <hr> +- This file is in the public domain, so clarified as of 2009-05-17 by +- Arthur David Olson. ++<hr> ++This web page is in the public domain, so clarified as of ++2009-05-17 by Arthur David Olson. ++<br> ++Please send corrections to this web page to the ++<a href="mailto:tz@iana.org">time zone mailing list</a>. ++The mailing list and its archives are public, ++so please do not send confidential information. + </footer> + </body> + </html> +--- contrib/tzdata/version.orig ++++ contrib/tzdata/version +@@ -1 +1 @@ +-2025b ++2026b +--- contrib/tzdata/zone.tab.orig ++++ contrib/tzdata/zone.tab +@@ -124,12 +124,12 @@ + CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) + CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) + CA +682059-1334300 America/Inuvik Mountain - NT (west) ++CA +4916-12307 America/Vancouver MST - BC (most areas) + CA +4906-11631 America/Creston MST - BC (Creston) + CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) + CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) + CA +6043-13503 America/Whitehorse MST - Yukon (east) + CA +6404-13925 America/Dawson MST - Yukon (west) +-CA +4916-12307 America/Vancouver Pacific - BC (most areas) + CC -1210+09655 Indian/Cocos + CD -0418+01518 Africa/Kinshasa Dem. Rep. of Congo (west) + CD -1140+02728 Africa/Lubumbashi Dem. Rep. of Congo (east) +--- contrib/tzdata/zone1970.tab.orig ++++ contrib/tzdata/zone1970.tab +@@ -2,10 +2,10 @@ + # + # This file is in the public domain. + # +-# From Paul Eggert (2018-06-27): ++# From Paul Eggert (2025-05-15): + # This file contains a table where each row stands for a timezone where + # civil timestamps have agreed since 1970. Columns are separated by +-# a single tab. Lines beginning with '#' are comments. All text uses ++# a single tab. Lines beginning with ‘#’ are comments. All text uses + # UTF-8 encoding. The columns of the table are as follows: + # + # 1. The countries that overlap the timezone, as a comma-separated list +@@ -116,11 +116,11 @@ + CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) + CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) + CA +682059-1334300 America/Inuvik Mountain - NT (west) ++CA +4916-12307 America/Vancouver MST - BC (most areas) + CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) + CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) + CA +6043-13503 America/Whitehorse MST - Yukon (east) + CA +6404-13925 America/Dawson MST - Yukon (west) +-CA +4916-12307 America/Vancouver Pacific - BC (most areas) + CH,DE,LI +4723+00832 Europe/Zurich Büsingen + CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan + CK -2114-15946 Pacific/Rarotonga +@@ -198,7 +198,7 @@ + KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay + KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe + KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau +-KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev ++KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur’yev + KZ +5113+05121 Asia/Oral West Kazakhstan + LB +3353+03530 Asia/Beirut + LK +0656+07951 Asia/Colombo +@@ -246,7 +246,7 @@ + PF -1732-14934 Pacific/Tahiti Society Islands + PF -0900-13930 Pacific/Marquesas Marquesas Islands + PF -2308-13457 Pacific/Gambier Gambier Islands +-PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d'Urville ++PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d’Urville + PG -0613+15534 Pacific/Bougainville Bougainville + PH +143512+1205804 Asia/Manila + PK +2452+06703 Asia/Karachi +@@ -266,7 +266,7 @@ + RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade + RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad + RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area +-# Mention RU and UA alphabetically. See "territorial claims" above. ++# Mention RU and UA alphabetically. See “territorial claims” above. + RU,UA +4457+03406 Europe/Simferopol Crimea + RU +5836+04939 Europe/Kirov MSK+00 - Kirov + RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd +@@ -354,20 +354,20 @@ + # The next section contains experimental tab-separated comments for + # use by user agents like tzselect that identify continents and oceans. + # +-# For example, the comment "#@AQ<tab>Antarctica/" means the country code ++# For example, the comment ‘#@AQ<tab>Antarctica/’ means the country code + # AQ is in the continent Antarctica regardless of the Zone name, + # so Pacific/Auckland should be listed under Antarctica as well as +-# under the Pacific because its line's country codes include AQ. ++# under the Pacific because its line’s country codes include AQ. + # + # If more than one country code is affected each is listed separated +-# by commas, e.g., #@IS,SH<tab>Atlantic/". If a country code is in ++# by commas, e.g., ‘#@IS,SH<tab>Atlantic/’. If a country code is in + # more than one continent or ocean, each is listed separated by +-# commas, e.g., the second column of "#@CY,TR<tab>Asia/,Europe/". ++# commas, e.g., the second column of ‘#@CY,TR<tab>Asia/,Europe/’. + # + # These experimental comments are present only for country codes where + # the continent or ocean is not already obvious from the Zone name. + # For example, there is no such comment for RU since it already +-# corresponds to Zone names starting with both "Europe/" and "Asia/". ++# corresponds to Zone names starting with both ‘Europe/’ and ‘Asia/’. + # + #@AQ Antarctica/ + #@IS,SH Atlantic/ +--- contrib/tzdata/zonenow.tab.orig ++++ contrib/tzdata/zonenow.tab +@@ -5,12 +5,12 @@ + # From Paul Eggert (2023-12-18): + # This file contains a table where each row stands for a timezone + # where civil timestamps are predicted to agree from now on. +-# This file is like zone1970.tab (see zone1970.tab's comments), ++# This file is like zone1970.tab (see zone1970.tab’s comments), + # but with the following changes: + # + # 1. Each timezone corresponds to a set of clocks that are planned + # to agree from now on. This is a larger set of clocks than in +-# zone1970.tab, where each timezone's clocks must agree from 1970 on. ++# zone1970.tab, where each timezone’s clocks must agree from 1970 on. + # 2. The first column is irrelevant and ignored. + # 3. The table is sorted in a different way: + # first by standard time UTC offset; +@@ -29,19 +29,19 @@ + #XX coordinates TZ comments + # + # -11 - SST +-XX -1416-17042 Pacific/Pago_Pago Midway; Samoa ("SST") ++XX -1416-17042 Pacific/Pago_Pago Midway; Samoa (SST) + # + # -11 + XX -1901-16955 Pacific/Niue Niue + # + # -10 - HST +-XX +211825-1575130 Pacific/Honolulu Hawaii ("HST") ++XX +211825-1575130 Pacific/Honolulu Hawaii (HST) + # + # -10 + XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands + # + # -10/-09 - HST / HDT (North America DST) +-XX +515248-1763929 America/Adak western Aleutians in Alaska ("HST/HDT") ++XX +515248-1763929 America/Adak western Aleutians in Alaska (HST/HDT) + # + # -09:30 + XX -0900-13930 Pacific/Marquesas Marquesas +@@ -50,58 +50,61 @@ + XX -2308-13457 Pacific/Gambier Gambier + # + # -09/-08 - AKST/AKDT (North America DST) +-XX +611305-1495401 America/Anchorage most of Alaska ("AKST/AKDT") ++XX +611305-1495401 America/Anchorage most of Alaska (AKST/AKDT) + # + # -08 + XX -2504-13005 Pacific/Pitcairn Pitcairn + # + # -08/-07 - PST/PDT (North America DST) +-XX +340308-1181434 America/Los_Angeles Pacific ("PST/PDT") - US & Canada; Mexico near US border ++XX +340308-1181434 America/Los_Angeles Pacific (PST/PDT) - US & Canada; Mexico near US border ++# ++# -08/-07 - PST/PDT (North America DST) until 2026-11-01 02:00; then MST ++XX +4916-12307 America/Vancouver MST - BC (most areas) + # + # -07 - MST +-XX +332654-1120424 America/Phoenix Mountain Standard ("MST") - Arizona; western Mexico; Yukon ++XX +332654-1120424 America/Phoenix Mountain Standard (MST) - Arizona; western Mexico; Yukon + # + # -07/-06 - MST/MDT (North America DST) +-XX +394421-1045903 America/Denver Mountain ("MST/MDT") - US & Canada; Mexico near US border ++XX +394421-1045903 America/Denver Mountain (MST/MDT) - US & Canada; Mexico near US border + # + # -06 + XX -0054-08936 Pacific/Galapagos Galápagos + # + # -06 - CST +-XX +1924-09909 America/Mexico_City Central Standard ("CST") - Saskatchewan; central Mexico; Central America ++XX +1924-09909 America/Mexico_City Central Standard (CST) - Saskatchewan; central Mexico; Central America + # + # -06/-05 (Chile DST) + XX -2709-10926 Pacific/Easter Easter Island + # + # -06/-05 - CST/CDT (North America DST) +-XX +415100-0873900 America/Chicago Central ("CST/CDT") - US & Canada; Mexico near US border ++XX +415100-0873900 America/Chicago Central (CST/CDT) - US & Canada; Mexico near US border + # + # -05 + XX -1203-07703 America/Lima eastern South America + # + # -05 - EST +-XX +175805-0764736 America/Jamaica Eastern Standard ("EST") - Caymans; Jamaica; eastern Mexico; Panama ++XX +175805-0764736 America/Jamaica Eastern Standard (EST) - Caymans; Jamaica; eastern Mexico; Panama + # + # -05/-04 - CST/CDT (Cuba DST) + XX +2308-08222 America/Havana Cuba + # + # -05/-04 - EST/EDT (North America DST) +-XX +404251-0740023 America/New_York Eastern ("EST/EDT") - US & Canada ++XX +404251-0740023 America/New_York Eastern (EST/EDT) - US & Canada + # + # -04 + XX +1030-06656 America/Caracas western South America + # + # -04 - AST +-XX +1828-06954 America/Santo_Domingo Atlantic Standard ("AST") - eastern Caribbean ++XX +1828-06954 America/Santo_Domingo Atlantic Standard (AST) - eastern Caribbean + # + # -04/-03 (Chile DST) + XX -3327-07040 America/Santiago most of Chile + # + # -04/-03 - AST/ADT (North America DST) +-XX +4439-06336 America/Halifax Atlantic ("AST/ADT") - Canada; Bermuda ++XX +4439-06336 America/Halifax Atlantic (AST/ADT) - Canada; Bermuda + # + # -03:30/-02:30 - NST/NDT (North America DST) +-XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT") ++XX +4734-05243 America/St_Johns Newfoundland (NST/NDT) + # + # -03 + XX -2332-04637 America/Sao_Paulo eastern and southern South America +@@ -122,43 +125,43 @@ + XX +3744-02540 Atlantic/Azores Azores + # + # +00 - GMT +-XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT") ++XX +0519-00402 Africa/Abidjan far western Africa; Iceland (GMT) + # + # +00/+01 - GMT/BST (EU DST) +-XX +513030-0000731 Europe/London United Kingdom ("GMT/BST") ++XX +513030-0000731 Europe/London United Kingdom (GMT/BST) + # + # +00/+01 - WET/WEST (EU DST) +-XX +3843-00908 Europe/Lisbon western Europe ("WET/WEST") ++XX +3843-00908 Europe/Lisbon western Europe (WET/WEST) + # + # +00/+02 - Troll DST + XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica + # + # +01 - CET +-XX +3647+00303 Africa/Algiers Algeria, Tunisia ("CET") ++XX +3647+00303 Africa/Algiers Algeria, Tunisia (CET) + # + # +01 - WAT +-XX +0627+00324 Africa/Lagos western Africa ("WAT") ++XX +0627+00324 Africa/Lagos western Africa (WAT) + # + # +01/+00 - IST/GMT (EU DST in reverse) +-XX +5320-00615 Europe/Dublin Ireland ("IST/GMT") ++XX +5320-00615 Europe/Dublin Ireland (IST/GMT) + # + # +01/+00 - (Morocco DST) + XX +3339-00735 Africa/Casablanca Morocco + # + # +01/+02 - CET/CEST (EU DST) +-XX +4852+00220 Europe/Paris central Europe ("CET/CEST") ++XX +4852+00220 Europe/Paris central Europe (CET/CEST) + # + # +02 - CAT +-XX -2558+03235 Africa/Maputo central Africa ("CAT") ++XX -2558+03235 Africa/Maputo central Africa (CAT) + # + # +02 - EET +-XX +3254+01311 Africa/Tripoli Libya; Kaliningrad ("EET") ++XX +3254+01311 Africa/Tripoli Libya; Kaliningrad (EET) + # + # +02 - SAST +-XX -2615+02800 Africa/Johannesburg southern Africa ("SAST") ++XX -2615+02800 Africa/Johannesburg southern Africa (SAST) + # + # +02/+03 - EET/EEST (EU DST) +-XX +3758+02343 Europe/Athens eastern Europe ("EET/EEST") ++XX +3758+02343 Europe/Athens eastern Europe (EET/EEST) + # + # +02/+03 - EET/EEST (Egypt DST) + XX +3003+03115 Africa/Cairo Egypt +@@ -166,9 +169,6 @@ + # +02/+03 - EET/EEST (Lebanon DST) + XX +3353+03530 Asia/Beirut Lebanon + # +-# +02/+03 - EET/EEST (Moldova DST) +-XX +4700+02850 Europe/Chisinau Moldova +-# + # +02/+03 - EET/EEST (Palestine DST) + XX +3130+03428 Asia/Gaza Palestine + # +@@ -179,10 +179,10 @@ + XX +4101+02858 Europe/Istanbul Near East; Belarus + # + # +03 - EAT +-XX -0117+03649 Africa/Nairobi eastern Africa ("EAT") ++XX -0117+03649 Africa/Nairobi eastern Africa (EAT) + # + # +03 - MSK +-XX +554521+0373704 Europe/Moscow Moscow ("MSK") ++XX +554521+0373704 Europe/Moscow Moscow (MSK) + # + # +03:30 + XX +3540+05126 Asia/Tehran Iran +@@ -197,13 +197,13 @@ + XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives + # + # +05 - PKT +-XX +2452+06703 Asia/Karachi Pakistan ("PKT") ++XX +2452+06703 Asia/Karachi Pakistan (PKT) + # + # +05:30 + XX +0656+07951 Asia/Colombo Sri Lanka + # + # +05:30 - IST +-XX +2232+08822 Asia/Kolkata India ("IST") ++XX +2232+08822 Asia/Kolkata India (IST) + # + # +05:45 + XX +2743+08519 Asia/Kathmandu Nepal +@@ -218,25 +218,25 @@ + XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island + # + # +07 - WIB +-XX -0610+10648 Asia/Jakarta Indonesia ("WIB") ++XX -0610+10648 Asia/Jakarta Indonesia (WIB) + # + # +08 + XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore; Concordia + # + # +08 - AWST +-XX -3157+11551 Australia/Perth Western Australia ("AWST") ++XX -3157+11551 Australia/Perth Western Australia (AWST) + # + # +08 - CST +-XX +3114+12128 Asia/Shanghai China ("CST") ++XX +3114+12128 Asia/Shanghai China (CST) + # + # +08 - HKT +-XX +2217+11409 Asia/Hong_Kong Hong Kong ("HKT") ++XX +2217+11409 Asia/Hong_Kong Hong Kong (HKT) + # + # +08 - PHT +-XX +143512+1205804 Asia/Manila Philippines ("PHT") ++XX +143512+1205804 Asia/Manila Philippines (PHT) + # + # +08 - WITA +-XX -0507+11924 Asia/Makassar Indonesia ("WITA") ++XX -0507+11924 Asia/Makassar Indonesia (WITA) + # + # +08:45 + XX -3143+12852 Australia/Eucla Eucla +@@ -245,31 +245,31 @@ + XX +5203+11328 Asia/Chita Russia; Palau; East Timor + # + # +09 - JST +-XX +353916+1394441 Asia/Tokyo Japan ("JST"); Eyre Bird Observatory ++XX +353916+1394441 Asia/Tokyo Japan (JST); Eyre Bird Observatory + # + # +09 - KST +-XX +3733+12658 Asia/Seoul Korea ("KST") ++XX +3733+12658 Asia/Seoul Korea (KST) + # + # +09 - WIT +-XX -0232+14042 Asia/Jayapura Indonesia ("WIT") ++XX -0232+14042 Asia/Jayapura Indonesia (WIT) + # + # +09:30 - ACST +-XX -1228+13050 Australia/Darwin Northern Territory ("ACST") ++XX -1228+13050 Australia/Darwin Northern Territory (ACST) + # + # +09:30/+10:30 - ACST/ACDT (Australia DST) +-XX -3455+13835 Australia/Adelaide South Australia ("ACST/ACDT") ++XX -3455+13835 Australia/Adelaide South Australia (ACST/ACDT) + # + # +10 +-XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d'Urville ++XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d’Urville + # + # +10 - AEST +-XX -2728+15302 Australia/Brisbane Queensland ("AEST") ++XX -2728+15302 Australia/Brisbane Queensland (AEST) + # + # +10 - ChST +-XX +1328+14445 Pacific/Guam Mariana Islands ("ChST") ++XX +1328+14445 Pacific/Guam Mariana Islands (ChST) + # + # +10/+11 - AEST/AEDT (Australia DST) +-XX -3352+15113 Australia/Sydney southeast Australia ("AEST/AEDT") ++XX -3352+15113 Australia/Sydney southeast Australia (AEST/AEDT) + # + # +10:30/+11 + XX -3133+15905 Australia/Lord_Howe Lord Howe Island +@@ -284,7 +284,7 @@ + XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc. + # + # +12/+13 (New Zealand DST) +-XX -3652+17446 Pacific/Auckland New Zealand ("NZST/NZDT") ++XX -3652+17446 Pacific/Auckland New Zealand (NZST/NZDT) + # + # +12:45/+13:45 (Chatham DST) + XX -4357-17633 Pacific/Chatham Chatham Islands diff --git a/website/static/security/patches/EN-26:09/tzdata-2026b.patch.asc b/website/static/security/patches/EN-26:09/tzdata-2026b.patch.asc new file mode 100644 index 0000000000..21648dd7c3 --- /dev/null +++ b/website/static/security/patches/EN-26:09/tzdata-2026b.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRYbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvd6UP/Avltou+mLznxdXMu4vA +iBiOSsZhwcjrL7Bj+loLwYApUlEvS4LGVn3P4tME8ka77QXUmct+0A82ShYLnrCU +PX/Hpi3Hh4OyhbyqzthJ/gDeLutLRrvgZS7Cm5bAGwN5W7l3kyAuMbxPPhlb4Sfy +2BkSyRwps6RD7hDGZxqMXKnKXctjVeubRUmDWpdgRdwZ52md+4RP2xK7ORw/recS +g93mFTbJCrkRCwxwdOMC7/VgmiteC5T7cyODJiTtLgfv6ZSjzOscGxJ7zFxNXwUn +ufaULotGMCJxQTOkQoOa81ISQW7fiOAKGuJJKn8rxe9WxmVQB31LimKYjePgjNGv +SkeXcNi+qC09xxUIP9Y5PTWgdMkLQF5fygrkTPK3wI2g88++j9khVP6fYH/YrgYF +opccYeVaBkG3aHxmyrLyIR8x0y157vFnE59Pox1JcF5HhfWbebtN9UAzXCsUkMnV +QpXjC8KNmWcjiu8baLdVgf61t1z3Jw7JRyObCIwzuDYCS+tMeaeFuGvtpYGtLD4T +Z1XGXmVXNJ1231fDEorxQL3P74yzlJJyPnxwUlWbrcMPJTcsL9FeY5uxsmNWXYYc +QOJYDlDIOYC3DXO2gwSr6kYZi+gwPPz+E8+JyaQizotl8r3VGZbkp+qpaSFrwOJx +9HU/KV0GERJTOjXhjxJh9Fnq +=uhBq +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:10/amd64.patch b/website/static/security/patches/EN-26:10/amd64.patch new file mode 100644 index 0000000000..0d35078623 --- /dev/null +++ b/website/static/security/patches/EN-26:10/amd64.patch @@ -0,0 +1,34 @@ +--- sys/amd64/amd64/mp_machdep.c.orig ++++ sys/amd64/amd64/mp_machdep.c +@@ -726,25 +726,12 @@ + addr2 = round_page(addr2); + total = atop(addr2 - addr1); + for (va = addr1; total > 0;) { +- if ((va & PDRMASK) != 0 || total < NPDEPG) { +- cnt = atop(NBPDR - (va & PDRMASK)); +- if (cnt > total) +- cnt = total; +- if (cnt > invlpgb_maxcnt + 1) +- cnt = invlpgb_maxcnt + 1; +- invlpgb(INVLPGB_GLOB | INVLPGB_VA | va, 0, +- cnt - 1); +- va += ptoa(cnt); +- total -= cnt; +- } else { +- cnt = total / NPTEPG; +- if (cnt > invlpgb_maxcnt + 1) +- cnt = invlpgb_maxcnt + 1; +- invlpgb(INVLPGB_GLOB | INVLPGB_VA | va, 0, +- INVLPGB_2M_CNT | (cnt - 1)); +- va += cnt << PDRSHIFT; +- total -= cnt * NPTEPG; +- } ++ cnt = MIN(total, invlpgb_maxcnt + 1); ++ /* 4K increments because these may not be superpages. */ ++ invlpgb(INVLPGB_GLOB | INVLPGB_VA | va, 0, ++ cnt - 1); ++ va += ptoa(cnt); ++ total -= cnt; + } + tlbsync(); + sched_unpin(); diff --git a/website/static/security/patches/EN-26:10/amd64.patch.asc b/website/static/security/patches/EN-26:10/amd64.patch.asc new file mode 100644 index 0000000000..3b578c4e1d --- /dev/null +++ b/website/static/security/patches/EN-26:10/amd64.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySRgbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvDpwQAJ7oyIO8545FSVCgFIME +sMFM9i57hzKz5lGjLcGHH9MDf09sEWpBQttcNo38bSsGKRuFZHK9uFA3yzTZ2Kex +AvCrcyxVgw0Z686H8gnJdBlf3Aevypcr9LI/eH9OZYvrhjPeXDescOUY2J6OnI9c +4hGKRgP6HUpilXvPz0p4WtnJJgYcK1RvfntESblS4Soyyh+vkNNrDWnoGlbi9TA8 +OGh62d54kF9adfBkki2pc0tpWs5zL5PcurdYOcRvEp/zatFtTV3tbVDByBkZo+XA +8JHfJF8DgEPI6o0sdfDwUK4xhhszIepSaVchgBJqxBPFHW8Om7dNs1DYeIvMlOLm +5dtxSKA74j6x2htr0uQAEQSjca5HHOJNv3ozZrO7iQw+8qBPACV7OYRQf3JutWle +nbMtsTc4AFNjV/uUvlXNnpLpcNv5EqgoTee67TN7w25CMK88jGjlBPrBQMf/zHRM +RLPTCkBbbY7C+OF6dG+Cgf7e+bFkSu44xxsT0lkjpquzbkVbLQOB7Y/zZ07N2r/x +pHz/QRiyl6AjrBkVjpnjx7aTejbr5iRG6v/fB/2eGfZa2QuINLrmCucvMaSGFd7d +LCCMztS1DdRQranH4/I0yf2m45CkdhvKR+cRQceThj3lEobADa8d7yF8O7ZqK24M +qE/QXWYyHkFQ2ckNDM807QLm +=9sYQ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:11/dhclient.patch b/website/static/security/patches/EN-26:11/dhclient.patch new file mode 100644 index 0000000000..c4f4a88d9a --- /dev/null +++ b/website/static/security/patches/EN-26:11/dhclient.patch @@ -0,0 +1,112 @@ +--- sbin/dhclient/dhclient.c.orig ++++ sbin/dhclient/dhclient.c +@@ -1161,7 +1161,7 @@ + lease = malloc(sizeof(struct client_lease)); + + if (!lease) { +- warning("dhcpoffer: no memory to record lease."); ++ warning("dhcpoffer: no memory to record lease"); + return (NULL); + } + +@@ -1211,7 +1211,7 @@ + + /* If the server name was filled out, copy it. + Do not attempt to validate the server name as a host name. +- RFC 2131 merely states that sname is NUL-terminated (which do ++ RFC 2131 merely states that sname is NUL-terminated (which we + do not assume) and that it is the server's host name. Since + the ISC client and server allow arbitrary characters, we do + as well. */ +@@ -1219,39 +1219,72 @@ + !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) && + packet->raw->sname[0]) { + lease->server_name = malloc(DHCP_SNAME_LEN + 1); +- if (!lease->server_name) { +- warning("dhcpoffer: no memory for server name."); ++ if (lease->server_name == NULL) { ++ warning("dhcpoffer: no memory for server name"); + free_client_lease(lease); + return (NULL); + } +- memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); +- lease->server_name[DHCP_SNAME_LEN]='\0'; +- if (strchr(lease->server_name, '"') != NULL || +- strchr(lease->server_name, '\\') != NULL) { +- warning("dhcpoffer: server name contains invalid characters."); +- free_client_lease(lease); +- return (NULL); ++ for (i = 0; i < DHCP_SNAME_LEN; i++) { ++ if (packet->raw->sname[i] == '\0') { ++ break; ++ } ++ if (packet->raw->sname[i] < ' ' || ++ packet->raw->sname[i] == '"' || ++ packet->raw->sname[i] == '\\') { ++ warning("dhcpoffer: server name contains " ++ "unsafe characters"); ++ free(lease->server_name); ++ lease->server_name = NULL; ++ break; ++ } ++ lease->server_name[i] = packet->raw->sname[i]; ++ } ++ /* Terminate and zero-pad */ ++ if (lease->server_name != NULL) { ++ while (i < DHCP_SNAME_LEN + 1) { ++ lease->server_name[i++] = '\0'; ++ } + } + } + +- /* Ditto for the filename. */ ++ /* Ditto for the file name. */ + if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || + !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) && + packet->raw->file[0]) { + /* Don't count on the NUL terminator. */ + lease->filename = malloc(DHCP_FILE_LEN + 1); +- if (!lease->filename) { +- warning("dhcpoffer: no memory for filename."); ++ if (lease->filename == NULL) { ++ warning("dhcpoffer: no memory for file name"); + free_client_lease(lease); + return (NULL); + } +- memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN); +- lease->filename[DHCP_FILE_LEN]='\0'; +- if (strchr(lease->filename, '"') != NULL || +- strchr(lease->filename, '\\') != NULL) { +- warning("dhcpoffer: filename contains invalid characters."); +- free_client_lease(lease); +- return (NULL); ++ for (i = 0; i < DHCP_FILE_LEN; i++) { ++ if (packet->raw->file[i] == '\0') { ++ break; ++ } ++ if (packet->raw->file[i] < ' ' || ++ packet->raw->file[i] == '"') { ++ warning("dhcpoffer: file name contains " ++ "unsafe characters"); ++ free(lease->filename); ++ lease->filename = NULL; ++ break; ++ } ++ if (packet->raw->file[i] == '\\') { ++ /* ++ * This is common in Windows-centric ++ * environments. Instead of rejecting, ++ * silently convert to forward slash. ++ */ ++ packet->raw->file[i] = '/'; ++ } ++ lease->filename[i] = packet->raw->file[i]; ++ } ++ /* Terminate and zero-pad */ ++ if (lease->filename != NULL) { ++ while (i < DHCP_FILE_LEN + 1) { ++ lease->filename[i++] = '\0'; ++ } + } + } + return lease; diff --git a/website/static/security/patches/EN-26:11/dhclient.patch.asc b/website/static/security/patches/EN-26:11/dhclient.patch.asc new file mode 100644 index 0000000000..e663d9bde6 --- /dev/null +++ b/website/static/security/patches/EN-26:11/dhclient.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiUbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvP3IP/jxonX89dJSBsH0i12F0 +dVgVOeCYMf9dhEnd9Oyw/KY6p8OMWkNHg2D3rRR0wDzEf8k7RAVNoD87uKzOHfQk +IeKE6n5LubG3WdLbEnWSMScHjvJ7+8+vDbU2brkXdWaBQxqdZRJ/QReRvLvLHR/8 +2xomS4l3uS1He+xxCPXk5G116zaDfEZWnYL1rHEbBI81Nxnktb/mSNwHLxf41E3A +QdGOaPKCbuKKkq98Bo5zaTu9B/68iXq9yDGnPHJoUhZnpCSXA/21PNkUP+G4N1VG +6bzCgl7e0tWL048nBv7V8A0cyZ8K0rCSjurlPNF82QxGGUD/Z6qKaclpwuQO/X50 +t3gzh0nJ1g6/F/FmywVjZEDAUIIpgHkyMGlWdzqlzLZ1jymSRXnZGGJVGU1tpcPF +AZC/avfvGAZNrSXVaM5IoduzW7xLzlF4XyJt3aT2GbmegnVmfWD2hgIVzktq/bWj +5UfalA/T/+2dusWLtbnUVQrZLppQBe5XfH1uNUONwguV4YDQ0ndP9hGUV5UM40Os +RvrMnHGPjszURPWKN01V5GQRoMZkur/vIglOkFPLcKfr6rYRP4yxpJN70E1xV/pK +AIjKUxIflDtAUdcgL0uaJHGJX6O8R4eXrl2RjdPv8EGDJcz/Y+zULSDbujCbcLys +BT3xt7JyKXIB92PonZo28Xn5 +=2BEv +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:12/ensa-135.patch b/website/static/security/patches/EN-26:12/ensa-135.patch new file mode 100644 index 0000000000..e01596907a --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-135.patch @@ -0,0 +1,56 @@ +--- tests/sys/netpfil/pf/sctp.py.orig ++++ tests/sys/netpfil/pf/sctp.py +@@ -448,53 +448,6 @@ + + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) +- def test_initiate_tag_check(self): +- # Ensure we don't send ABORTs in response to the other end's INIT_ACK +- # That'd interfere with our test. +- ToolsHelper.print_output("/sbin/sysctl net.inet.sctp.blackhole=2") +- +- import scapy.all as sp +- +- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ +- / sp.SCTP(sport=1234, dport=1234) \ +- / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) +- packet.show() +- +- r = sp.sr1(packet, timeout=3) +- assert r +- r.show() +- assert r.getlayer(sp.SCTP) +- assert r.getlayer(sp.SCTPChunkInitAck) +- assert r.getlayer(sp.SCTP).tag == 1 +- +- # Send another INIT with the same initiate tag, expect another init ack +- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ +- / sp.SCTP(sport=1234, dport=1234) \ +- / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) +- packet.show() +- +- r = sp.sr1(packet, timeout=3) +- assert r +- r.show() +- assert r.getlayer(sp.SCTP) +- assert r.getlayer(sp.SCTPChunkInitAck) +- assert r.getlayer(sp.SCTP).tag == 1 +- +- # Send an INIT with a different initiate tag, expect another init ack +- packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ +- / sp.SCTP(sport=1234, dport=1234) \ +- / sp.SCTPChunkInit(init_tag=42, n_in_streams=1, n_out_streams=1, a_rwnd=1500) +- packet.show() +- +- r = sp.sr1(packet, timeout=3) +- assert r +- r.show() +- assert r.getlayer(sp.SCTP) +- assert r.getlayer(sp.SCTPChunkInitAck) +- assert r.getlayer(sp.SCTP).tag == 42 +- +- @pytest.mark.require_user("root") +- @pytest.mark.require_progs(["scapy"]) + def test_too_many_add_ip(self): + import scapy.all as sp + DEPTH=90 diff --git a/website/static/security/patches/EN-26:12/ensa-135.patch.asc b/website/static/security/patches/EN-26:12/ensa-135.patch.asc new file mode 100644 index 0000000000..b9015d82dd --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-135.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xigbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvKRoQAOoQG727h+K+Ggup1bPR +abGWXO72V+ouikfjx34bFYoZkti0/beAnH0/C8KhFCql23kdWVAk576nLz6a1TYe +6XAkw+MbsL/TN07xexstUfZzBlO6oZGvOed1fkGsK7FNdN47NvTn5bAaSDOIwyvr +c35FsjD2+ojqc+KdlyaNMidSlS58SbKtcZ1OrcJD3VMB3FJZ6D+ko0adCoXgyfPN +noaWId+aANmFTksykWsDAgMKEdlyE8d+/dAec9m9qDY6Yza1IgU3bi2jh91lAx/y +/n3QRfvdllFh1gJ+YTe0B1SpIimqjBnvGjUNNcDrpgbVrc5Yp9fPiPKSnxSit6eP +dcLNNs3o4yLBScG9R5raZ184H64Uv1boD69I1MFEGWi2qkGxlc0hREj5G5v2NOny +oGIOzA0yXEb9aXAAH1fP+WV9eADYheCQy3OJqZeJAEOda5actOKFfdoAOpNMNFAm +2gUlOZO2hrR6RNJiAAJO0vzusuo66Wx97FPJUez/SoQSHriNY/e+yOnnGWe1Fjp+ +2EYa/cUcfHTs5nGy+cUXCjYKL0AL7HD7kiEiOoTG2TT438RtcMNLDH29gjPsnY6F +nRBF7Sm994wwCKlWW1cmgxyZczpBVByHI8/mAT3i7wEyZsuBij0fkyIJZlHAxJQb +XPcrcVNqkzLQzucFwGQ1jczC +=Mn9N +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:12/ensa-143.patch b/website/static/security/patches/EN-26:12/ensa-143.patch new file mode 100644 index 0000000000..8b87835c4a --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-143.patch @@ -0,0 +1,487 @@ +--- lib/libnv/tests/Makefile.orig ++++ lib/libnv/tests/Makefile +@@ -1,6 +1,15 @@ ++.include <src.opts.mk> + + ATF_TESTS_C= \ + nvlist_send_recv_test ++ ++.PATH: ${SRCTOP}/lib/libnv ++SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c ++CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv ++CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv ++.if ${MK_ASAN} != "yes" ++CFLAGS.nvlist_send_recv_test+=-DNO_ASAN ++.endif + + ATF_TESTS_CXX= \ + cnv_tests \ +--- lib/libnv/tests/nv_array_tests.cc.orig ++++ lib/libnv/tests/nv_array_tests.cc +@@ -1,6 +1,5 @@ + /*- +- * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org> +- * All rights reserved. ++ * Copyright (c) 2015-2024 Mariusz Zaborski <oshogbo@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -28,6 +27,7 @@ + #include <sys/param.h> + #include <sys/types.h> + #include <sys/nv.h> ++#include <sys/mman.h> + #include <sys/socket.h> + + #include <atf-c++.hpp> +@@ -1162,6 +1162,58 @@ + free(packed); + } + ++ ++ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array_nonull__pack); ++ATF_TEST_CASE_BODY(nvlist_string_array_nonull__pack) ++{ ++ nvlist_t *testnvl, *unpacked; ++ const char *somestr[3] = { "a", "b", "XXX" }; ++ uint8_t *packed, *twopages, *dataptr, *secondpage; ++ size_t packed_size, page_size; ++ bool found; ++ ++ page_size = sysconf(_SC_PAGESIZE); ++ testnvl = nvlist_create(0); ++ ATF_REQUIRE(testnvl != NULL); ++ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0); ++ nvlist_add_string_array(testnvl, "nvl/string", somestr, ++ nitems(somestr)); ++ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0); ++ ++ packed = (uint8_t *)nvlist_pack(testnvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ++ twopages = (uint8_t *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ ATF_REQUIRE(twopages != MAP_FAILED); ++ dataptr = &twopages[page_size - packed_size]; ++ secondpage = &twopages[page_size]; ++ ++ memset(twopages, 'A', page_size * 2); ++ ++ mprotect(secondpage, page_size, PROT_NONE); ++ memcpy(dataptr, packed, packed_size); ++ ++ found = false; ++ for (size_t i = 0; i < packed_size - 3; i++) { ++ if (dataptr[i] == 'X' && dataptr[i + 1] == 'X' && ++ dataptr[i + 2] == 'X' && dataptr[i + 3] == '\0') { ++ dataptr[i + 3] = 'X'; ++ found = true; ++ break; ++ } ++ } ++ ATF_REQUIRE(found == true); ++ ++ unpacked = nvlist_unpack(dataptr, packed_size, 0); ++ ATF_REQUIRE(unpacked == NULL); ++ ++ nvlist_destroy(testnvl); ++ free(packed); ++ munmap(twopages, page_size * 2); ++} ++ ++ + ATF_INIT_TEST_CASES(tp) + { + +@@ -1191,5 +1243,7 @@ + ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack) + ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack) + ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack) ++ ++ ATF_ADD_TEST_CASE(tp, nvlist_string_array_nonull__pack) + } + +--- lib/libnv/tests/nvlist_send_recv_test.c.orig ++++ lib/libnv/tests/nvlist_send_recv_test.c +@@ -1,5 +1,8 @@ + /*- ++ * SPDX-License-Identifier: BSD-2-Clause ++ * + * Copyright (c) 2013 The FreeBSD Foundation ++ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org> + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. +@@ -28,6 +31,8 @@ + + #include <sys/cdefs.h> + #include <sys/param.h> ++#include <sys/resource.h> ++#include <sys/select.h> + #include <sys/socket.h> + #include <sys/sysctl.h> + #include <sys/wait.h> +@@ -44,6 +49,9 @@ + + #include <atf-c.h> + ++#include <nv_impl.h> ++#include <msgio.h> ++ + #define ALPHABET "abcdefghijklmnopqrstuvwxyz" + #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) + +@@ -531,6 +539,59 @@ + nvlist_send_recv__send_nvlist(SOCK_STREAM); + } + ++/* ++ * Regression test for fd_wait(): the previous select(2)-based implementation ++ * called FD_SET() unconditionally, which is an out-of-bounds stack write when ++ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE ++ * and verify a full nvlist round-trip still works. ++ */ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd); ++ATF_TC_BODY(nvlist_send_recv__highfd, tc) ++{ ++ struct rlimit rl; ++ nvlist_t *nvl; ++ int socks[2], hi_send, hi_recv, status; ++ pid_t pid; ++ ++ hi_send = FD_SETSIZE + 5; ++ hi_recv = FD_SETSIZE + 6; ++ ++ rl.rlim_cur = rl.rlim_max = hi_recv + 1; ++ if (setrlimit(RLIMIT_NOFILE, &rl) != 0) ++ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno)); ++ ++ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0); ++ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv); ++ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send); ++ (void)close(socks[0]); ++ (void)close(socks[1]); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ if (pid == 0) { ++ /* Child: send. */ ++ (void)close(hi_recv); ++ nvl = nvlist_create(0); ++ nvlist_add_string(nvl, "key", "value"); ++ if (nvlist_send(hi_send, nvl) != 0) ++ err(EXIT_FAILURE, "nvlist_send"); ++ nvlist_destroy(nvl); ++ _exit(0); ++ } ++ ++ (void)close(hi_send); ++ nvl = nvlist_recv(hi_recv, 0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_error(nvl) == 0); ++ ATF_REQUIRE(nvlist_exists_string(nvl, "key")); ++ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0); ++ nvlist_destroy(nvl); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ (void)close(hi_recv); ++} ++ + ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram); + ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc) + { +@@ -543,15 +604,260 @@ + nvlist_send_recv__send_closed_fd(SOCK_STREAM); + } + ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], status; ++ pid_t pid; ++ ++#ifdef NO_ASAN ++ atf_tc_skip("This test requires ASAN"); ++#endif ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)sizeof(struct nvlist_header)); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ errno = 0; ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ /* ++ * Make sure it has failed on EINVAL, and not on ++ * errors returned by malloc or recv. ++ */ ++ ATF_REQUIRE(errno == EINVAL); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ close(fd); ++ } ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x00, /* flags */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size); ++ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], status; ++ pid_t pid; ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ nvlist_add_string(nvl, "nvl/string", "test"); ++ ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_descriptors = 0x20; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)packed_size); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ } ++ ++ close(fd); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], fds[1], status; ++ pid_t pid; ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ nvlist_add_string(nvl, "nvl/string", "test"); ++ ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_descriptors = 0x4000000000000002; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)packed_size); ++ ++ fds[0] = dup(STDERR_FILENO); ++ ATF_REQUIRE(fds[0] >= 0); ++ ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ close(fds[0]); ++ close(fd); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ /* Make sure that fd was not parsed by nvlist */ ++ ATF_REQUIRE(fd_recv(fd, fds, 1) == 0); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ ++ close(fds[0]); ++ close(fd); ++ } ++} ++ + ATF_TP_ADD_TCS(tp) + { + + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream); ++ ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size); + + return (atf_no_error()); + } +--- sys/contrib/libnv/nv_impl.h.orig ++++ sys/contrib/libnv/nv_impl.h +@@ -42,6 +42,14 @@ + typedef struct nvpair nvpair_t; + #endif + ++struct nvlist_header { ++ uint8_t nvlh_magic; ++ uint8_t nvlh_version; ++ uint8_t nvlh_flags; ++ uint64_t nvlh_descriptors; ++ uint64_t nvlh_size; ++} __packed; ++ + #define NV_TYPE_NVLIST_ARRAY_NEXT 254 + #define NV_TYPE_NVLIST_UP 255 + +--- sys/contrib/libnv/nvlist.c.orig ++++ sys/contrib/libnv/nvlist.c +@@ -118,13 +118,6 @@ + + #define NVLIST_HEADER_MAGIC 0x6c + #define NVLIST_HEADER_VERSION 0x00 +-struct nvlist_header { +- uint8_t nvlh_magic; +- uint8_t nvlh_version; +- uint8_t nvlh_flags; +- uint64_t nvlh_descriptors; +- uint64_t nvlh_size; +-} __packed; + + nvlist_t * + nvlist_create(int flags) diff --git a/website/static/security/patches/EN-26:12/ensa-143.patch.asc b/website/static/security/patches/EN-26:12/ensa-143.patch.asc new file mode 100644 index 0000000000..817e56b18b --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-143.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xikbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvXoIQAMu1Z+MW43UPDQ7tLgn2 +4aVfe0l+NqdQS3t9diugP8SdwmSXuCgs6nnXFgp0s6iBRyDqWyHtc3w6eaf24QSD +Iho64XCvcZrik5QkLCE0agDZ4JutaPFy2Tkv1CWgeBmQyZl09LyYgILqtqIgK5qm +WZXhxDdPK+d16QRvHr06AhOWHqQzDo7/Exk5U82LrwuEbJCu9Szy5yTT5tBJrmIq +fvQYVYf2RLyNad2LA13xRLLCF0K/Tdpaj6TnkBLJragNwjCExBtnXyi+c4FCnqTF +7d+FzOAF2sgMSFxFh075FPXAlItfcMOIxUXjbH03vmXgxOV20izwQP0i3PRR3lPl +eGZobqaO7Oe7vhCJ1vgY2OPRuOr2VHrKQMcTAeQCCLYkN7MMjx1mWspRSWRTbIv5 +3KzZfy89v+NWO5vbXQ6zVqsknNUjeYbqbHS6Hlk5xr9kwYkxA0HBm/6RVwmVg5bm +dthtj7jtZcuiYQwgNuGp908SuZkU0g+MzzGijOvZ60nckfvx+CX/tAEWecDKn8zZ +V4UiEggNR5tSkqnNIfFtelAYtNGKX5lia/3lb/FijxM8mFgVjLC3IAyR5z8OSYDQ +zdYrC5aYsWUCFyBENN4VElz2RnJgIGFMRWFCfb4vpbHFC7Zo6ce6Rln1TnsuH0bE +MJH+dVpEzdrjYOq74oc0fHgA +=/8Ff +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:12/ensa-144.patch b/website/static/security/patches/EN-26:12/ensa-144.patch new file mode 100644 index 0000000000..8b87835c4a --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-144.patch @@ -0,0 +1,487 @@ +--- lib/libnv/tests/Makefile.orig ++++ lib/libnv/tests/Makefile +@@ -1,6 +1,15 @@ ++.include <src.opts.mk> + + ATF_TESTS_C= \ + nvlist_send_recv_test ++ ++.PATH: ${SRCTOP}/lib/libnv ++SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c ++CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv ++CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv ++.if ${MK_ASAN} != "yes" ++CFLAGS.nvlist_send_recv_test+=-DNO_ASAN ++.endif + + ATF_TESTS_CXX= \ + cnv_tests \ +--- lib/libnv/tests/nv_array_tests.cc.orig ++++ lib/libnv/tests/nv_array_tests.cc +@@ -1,6 +1,5 @@ + /*- +- * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org> +- * All rights reserved. ++ * Copyright (c) 2015-2024 Mariusz Zaborski <oshogbo@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -28,6 +27,7 @@ + #include <sys/param.h> + #include <sys/types.h> + #include <sys/nv.h> ++#include <sys/mman.h> + #include <sys/socket.h> + + #include <atf-c++.hpp> +@@ -1162,6 +1162,58 @@ + free(packed); + } + ++ ++ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array_nonull__pack); ++ATF_TEST_CASE_BODY(nvlist_string_array_nonull__pack) ++{ ++ nvlist_t *testnvl, *unpacked; ++ const char *somestr[3] = { "a", "b", "XXX" }; ++ uint8_t *packed, *twopages, *dataptr, *secondpage; ++ size_t packed_size, page_size; ++ bool found; ++ ++ page_size = sysconf(_SC_PAGESIZE); ++ testnvl = nvlist_create(0); ++ ATF_REQUIRE(testnvl != NULL); ++ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0); ++ nvlist_add_string_array(testnvl, "nvl/string", somestr, ++ nitems(somestr)); ++ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0); ++ ++ packed = (uint8_t *)nvlist_pack(testnvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ++ twopages = (uint8_t *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ ATF_REQUIRE(twopages != MAP_FAILED); ++ dataptr = &twopages[page_size - packed_size]; ++ secondpage = &twopages[page_size]; ++ ++ memset(twopages, 'A', page_size * 2); ++ ++ mprotect(secondpage, page_size, PROT_NONE); ++ memcpy(dataptr, packed, packed_size); ++ ++ found = false; ++ for (size_t i = 0; i < packed_size - 3; i++) { ++ if (dataptr[i] == 'X' && dataptr[i + 1] == 'X' && ++ dataptr[i + 2] == 'X' && dataptr[i + 3] == '\0') { ++ dataptr[i + 3] = 'X'; ++ found = true; ++ break; ++ } ++ } ++ ATF_REQUIRE(found == true); ++ ++ unpacked = nvlist_unpack(dataptr, packed_size, 0); ++ ATF_REQUIRE(unpacked == NULL); ++ ++ nvlist_destroy(testnvl); ++ free(packed); ++ munmap(twopages, page_size * 2); ++} ++ ++ + ATF_INIT_TEST_CASES(tp) + { + +@@ -1191,5 +1243,7 @@ + ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack) + ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack) + ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack) ++ ++ ATF_ADD_TEST_CASE(tp, nvlist_string_array_nonull__pack) + } + +--- lib/libnv/tests/nvlist_send_recv_test.c.orig ++++ lib/libnv/tests/nvlist_send_recv_test.c +@@ -1,5 +1,8 @@ + /*- ++ * SPDX-License-Identifier: BSD-2-Clause ++ * + * Copyright (c) 2013 The FreeBSD Foundation ++ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org> + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. +@@ -28,6 +31,8 @@ + + #include <sys/cdefs.h> + #include <sys/param.h> ++#include <sys/resource.h> ++#include <sys/select.h> + #include <sys/socket.h> + #include <sys/sysctl.h> + #include <sys/wait.h> +@@ -44,6 +49,9 @@ + + #include <atf-c.h> + ++#include <nv_impl.h> ++#include <msgio.h> ++ + #define ALPHABET "abcdefghijklmnopqrstuvwxyz" + #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) + +@@ -531,6 +539,59 @@ + nvlist_send_recv__send_nvlist(SOCK_STREAM); + } + ++/* ++ * Regression test for fd_wait(): the previous select(2)-based implementation ++ * called FD_SET() unconditionally, which is an out-of-bounds stack write when ++ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE ++ * and verify a full nvlist round-trip still works. ++ */ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd); ++ATF_TC_BODY(nvlist_send_recv__highfd, tc) ++{ ++ struct rlimit rl; ++ nvlist_t *nvl; ++ int socks[2], hi_send, hi_recv, status; ++ pid_t pid; ++ ++ hi_send = FD_SETSIZE + 5; ++ hi_recv = FD_SETSIZE + 6; ++ ++ rl.rlim_cur = rl.rlim_max = hi_recv + 1; ++ if (setrlimit(RLIMIT_NOFILE, &rl) != 0) ++ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno)); ++ ++ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0); ++ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv); ++ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send); ++ (void)close(socks[0]); ++ (void)close(socks[1]); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ if (pid == 0) { ++ /* Child: send. */ ++ (void)close(hi_recv); ++ nvl = nvlist_create(0); ++ nvlist_add_string(nvl, "key", "value"); ++ if (nvlist_send(hi_send, nvl) != 0) ++ err(EXIT_FAILURE, "nvlist_send"); ++ nvlist_destroy(nvl); ++ _exit(0); ++ } ++ ++ (void)close(hi_send); ++ nvl = nvlist_recv(hi_recv, 0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_error(nvl) == 0); ++ ATF_REQUIRE(nvlist_exists_string(nvl, "key")); ++ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0); ++ nvlist_destroy(nvl); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ (void)close(hi_recv); ++} ++ + ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram); + ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc) + { +@@ -543,15 +604,260 @@ + nvlist_send_recv__send_closed_fd(SOCK_STREAM); + } + ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], status; ++ pid_t pid; ++ ++#ifdef NO_ASAN ++ atf_tc_skip("This test requires ASAN"); ++#endif ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)sizeof(struct nvlist_header)); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ errno = 0; ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ /* ++ * Make sure it has failed on EINVAL, and not on ++ * errors returned by malloc or recv. ++ */ ++ ATF_REQUIRE(errno == EINVAL); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ close(fd); ++ } ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x00, /* flags */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size); ++ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], status; ++ pid_t pid; ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ nvlist_add_string(nvl, "nvl/string", "test"); ++ ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_descriptors = 0x20; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)packed_size); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ } ++ ++ close(fd); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc) ++{ ++ nvlist_t *nvl; ++ void *packed; ++ size_t packed_size; ++ struct nvlist_header *header; ++ int fd, socks[2], fds[1], status; ++ pid_t pid; ++ ++ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ ++ if (pid == 0) { ++ /* Child. */ ++ fd = socks[0]; ++ close(socks[1]); ++ ++ nvl = nvlist_create(0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_empty(nvl)); ++ ++ nvlist_add_string(nvl, "nvl/string", "test"); ++ ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ++ ++ packed = nvlist_pack(nvl, &packed_size); ++ ATF_REQUIRE(packed != NULL); ++ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header)); ++ ++ header = (struct nvlist_header *)packed; ++ header->nvlh_descriptors = 0x4000000000000002; ++ ++ ATF_REQUIRE_EQ(write(fd, packed, packed_size), ++ (ssize_t)packed_size); ++ ++ fds[0] = dup(STDERR_FILENO); ++ ATF_REQUIRE(fds[0] >= 0); ++ ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0); ++ ++ nvlist_destroy(nvl); ++ free(packed); ++ ++ close(fds[0]); ++ close(fd); ++ ++ exit(0); ++ } else { ++ /* Parent */ ++ fd = socks[1]; ++ close(socks[0]); ++ ++ nvl = nvlist_recv(fd, 0); ++ ATF_REQUIRE(nvl == NULL); ++ ++ /* Make sure that fd was not parsed by nvlist */ ++ ATF_REQUIRE(fd_recv(fd, fds, 1) == 0); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ ++ close(fds[0]); ++ close(fd); ++ } ++} ++ + ATF_TP_ADD_TCS(tp) + { + + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream); ++ ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size); + + return (atf_no_error()); + } +--- sys/contrib/libnv/nv_impl.h.orig ++++ sys/contrib/libnv/nv_impl.h +@@ -42,6 +42,14 @@ + typedef struct nvpair nvpair_t; + #endif + ++struct nvlist_header { ++ uint8_t nvlh_magic; ++ uint8_t nvlh_version; ++ uint8_t nvlh_flags; ++ uint64_t nvlh_descriptors; ++ uint64_t nvlh_size; ++} __packed; ++ + #define NV_TYPE_NVLIST_ARRAY_NEXT 254 + #define NV_TYPE_NVLIST_UP 255 + +--- sys/contrib/libnv/nvlist.c.orig ++++ sys/contrib/libnv/nvlist.c +@@ -118,13 +118,6 @@ + + #define NVLIST_HEADER_MAGIC 0x6c + #define NVLIST_HEADER_VERSION 0x00 +-struct nvlist_header { +- uint8_t nvlh_magic; +- uint8_t nvlh_version; +- uint8_t nvlh_flags; +- uint64_t nvlh_descriptors; +- uint64_t nvlh_size; +-} __packed; + + nvlist_t * + nvlist_create(int flags) diff --git a/website/static/security/patches/EN-26:12/ensa-144.patch.asc b/website/static/security/patches/EN-26:12/ensa-144.patch.asc new file mode 100644 index 0000000000..4c41ef8f55 --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-144.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xiobFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvsj4QAKU6z5Bwr7Mz1EuIurfY +KWC8nPyOciXn+b0pITMGZKKmYOOk3uhjcVwuQa3BRL0XGFEVm2b1GSO7exvSHTjo +TUD/w80wyzjiqUV3T7LfXZD2hZKnIL3erCDKwgmXX3D5cSOjjKQPaDgb/ax0Jk+G +/mccSWKg+4oMrISwcD2urimU5OZcvrgTNNksRnFtVlKb1bKttdTIERtcB40fb3G9 +6CAI6Gwpg/OzARHICC9GgMrrSvnaknL5peMLfTpwNBwdYJJLJLXuGVlugKnH46/3 +py5e1zdbR6Y/ieEhJpZ3bhHV38UZBgstVGCmtpMPVFXo7N6ustrBM+861CeLGez4 +ct9d8LcHMNoOGtFkzDsWL/Pp99TV8wYEVoVVZkx0dJv/awzmmasAN8q9KN4tlTzB ++4DHYIToTRdhghpp9aRm7ZCoShKARpbSp4XH1sOdj6t82MR/mIDQnvl+t7uw69oY +Y3Ch+atdUuZAU+2RcxGPlcQJ4bhQ2UlXG1fZnyD6HeizkTCZaOlLn2aSmPtpv+bH +nihTiuLFCPcpmdrNsj6ukVBBftpojF9Jufo4d95sKgOr1mImYWBJUjCIZjc3bHFL +Qk/GnOSKgsD9UQjgtoQoQlZRmjTBlX04HqMgE4TBfjrnfb/5jezIlxE/TPpA4wrU +/eawpZgNuXq1uaBn/w1aNBkE +=rZUQ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/EN-26:12/ensa-150.patch b/website/static/security/patches/EN-26:12/ensa-150.patch new file mode 100644 index 0000000000..7adccac45b --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-150.patch @@ -0,0 +1,166 @@ +--- lib/libnv/tests/nvlist_send_recv_test.c.orig ++++ lib/libnv/tests/nvlist_send_recv_test.c +@@ -1,5 +1,8 @@ + /*- ++ * SPDX-License-Identifier: BSD-2-Clause ++ * + * Copyright (c) 2013 The FreeBSD Foundation ++ * Copyright (c) 2024-2026 Mariusz Zaborski <oshogbo@FreeBSD.org> + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. +@@ -27,6 +30,8 @@ + */ + + #include <sys/param.h> ++#include <sys/resource.h> ++#include <sys/select.h> + #include <sys/socket.h> + #include <sys/sysctl.h> + #include <sys/wait.h> +@@ -533,6 +538,59 @@ + nvlist_send_recv__send_nvlist(SOCK_STREAM); + } + ++/* ++ * Regression test for fd_wait(): the previous select(2)-based implementation ++ * called FD_SET() unconditionally, which is an out-of-bounds stack write when ++ * the socket fd is >= FD_SETSIZE. Force the socketpair fds above FD_SETSIZE ++ * and verify a full nvlist round-trip still works. ++ */ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__highfd); ++ATF_TC_BODY(nvlist_send_recv__highfd, tc) ++{ ++ struct rlimit rl; ++ nvlist_t *nvl; ++ int socks[2], hi_send, hi_recv, status; ++ pid_t pid; ++ ++ hi_send = FD_SETSIZE + 5; ++ hi_recv = FD_SETSIZE + 6; ++ ++ rl.rlim_cur = rl.rlim_max = hi_recv + 1; ++ if (setrlimit(RLIMIT_NOFILE, &rl) != 0) ++ atf_tc_skip("cannot raise RLIMIT_NOFILE: %s", strerror(errno)); ++ ++ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, socks) == 0); ++ ATF_REQUIRE(dup2(socks[0], hi_recv) == hi_recv); ++ ATF_REQUIRE(dup2(socks[1], hi_send) == hi_send); ++ (void)close(socks[0]); ++ (void)close(socks[1]); ++ ++ pid = fork(); ++ ATF_REQUIRE(pid >= 0); ++ if (pid == 0) { ++ /* Child: send. */ ++ (void)close(hi_recv); ++ nvl = nvlist_create(0); ++ nvlist_add_string(nvl, "key", "value"); ++ if (nvlist_send(hi_send, nvl) != 0) ++ err(EXIT_FAILURE, "nvlist_send"); ++ nvlist_destroy(nvl); ++ _exit(0); ++ } ++ ++ (void)close(hi_send); ++ nvl = nvlist_recv(hi_recv, 0); ++ ATF_REQUIRE(nvl != NULL); ++ ATF_REQUIRE(nvlist_error(nvl) == 0); ++ ATF_REQUIRE(nvlist_exists_string(nvl, "key")); ++ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "key"), "value") == 0); ++ nvlist_destroy(nvl); ++ ++ ATF_REQUIRE(waitpid(pid, &status, 0) == pid); ++ ATF_REQUIRE(status == 0); ++ (void)close(hi_recv); ++} ++ + ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram); + ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc) + { +@@ -608,6 +666,58 @@ + } + } + ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_big_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_big_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x80, /* flags: NV_FLAG_BIG_ENDIAN */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ ++ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_little_endian_size); ++ATF_TC_BODY(nvlist_send_recv__overflow_little_endian_size, tc) ++{ ++ static const unsigned char payload[] = { ++ 0x6c, /* magic */ ++ 0x00, /* version */ ++ 0x00, /* flags */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ }; ++ nvlist_t *nvl; ++ int sv[2]; ++ ++ ATF_REQUIRE_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); ++ ATF_REQUIRE_EQ(write(sv[1], payload, sizeof(payload)), ++ (ssize_t)sizeof(payload)); ++ ATF_REQUIRE_EQ(close(sv[1]), 0); ++ ++ errno = 0; ++ nvl = nvlist_recv(sv[0], 0); ++ ATF_REQUIRE(nvl == NULL); ++ ATF_REQUIRE_EQ(errno, EINVAL); ++ ++ ATF_REQUIRE_EQ(close(sv[0]), 0); ++} ++ + ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size); + ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc) + { +@@ -736,12 +846,15 @@ + + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__highfd); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram); + ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream); + + ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_big_endian_size); ++ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_little_endian_size); + ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size); + ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size); + +--- tests/sys/posixshm/posixshm_test.c.orig ++++ tests/sys/posixshm/posixshm_test.c +@@ -1986,7 +1986,7 @@ + error = sigaction(SIGSEGV, &sa, NULL); + ATF_REQUIRE(error == 0); + +- pscnt = pagesizes(ps, true); ++ pscnt = pagesizes(ps); + + for (int i = 1; i < pscnt; i++) { + uint64_t val; diff --git a/website/static/security/patches/EN-26:12/ensa-150.patch.asc b/website/static/security/patches/EN-26:12/ensa-150.patch.asc new file mode 100644 index 0000000000..494c016118 --- /dev/null +++ b/website/static/security/patches/EN-26:12/ensa-150.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmn0xisbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvZdYQAIY0794gvo9DtJHT/h1Z +y5ezNg6C3axx4X1Ug1dVGQoH/+isH/hvMzHM/826SaGFBlD65SM+pQeZb9sUeeA9 +N65cW1m3dt+k+SNfpZ583adcwQBGQuC1NvNUDyJJmEnozCWmmqXXBtciPEIQEZ9c +AmsSlL/TBVw1ruWPQ8nA/5xpPUEjAEw5CoMej9KG7/xziaYr5wC1e27FiDA8Z3Ar +LiA/NM+4FmgZQvUIRWCrzBhesdKFFYOl8QMriOrxucqCcp6bqzQGRi5izfnvFCYH +aWvN1FFe99+EYiVH3aQ1SoEBJ8etVPSrlhuOfic0WIhWlwKeL9Yvx9Be04LpJcu6 +3KY8Yr1O7mxQv8Jtwd7OeXUha2mDBLIxMtYs70SKgo+m1vfvLPoUckIDDszgIgCk +swZEWhuGKSQ1aAMx5+6eRESKnOqATLWV04MHuC+TTD2v5kQvI4lb/bna87wUDlbl +zSQn7FCv5KITrkhuFSF7vmoTUmB6EBDmfDvI2LSUKiHPAOwh8WJE4L0JoF9xgP2d +G8SsONb5gb8YghWtF1KbPQlobGLy44vqZ/o1QvAxs7wZxPDx2Rw66PpEVWHXZKjN +iXTAxheUwEYqMykzp7AQXuGvxeXrxfc6SoMLib1VsiRC4SGnVGaincF0jjqbeWeG +r7Nd/REiFerNNNgKJGLXa5N0 +=U/vY +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:01/openssl-13.patch b/website/static/security/patches/SA-26:01/openssl-13.patch new file mode 100644 index 0000000000..f0e9fb0194 --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-13.patch @@ -0,0 +1,194 @@ +--- crypto/openssl/apps/s_client.c.orig ++++ crypto/openssl/apps/s_client.c +@@ -2698,8 +2698,9 @@ + goto end; + } + atyp = ASN1_generate_nconf(genstr, cnf); +- if (atyp == NULL) { ++ if (atyp == NULL || atyp->type != V_ASN1_SEQUENCE) { + NCONF_free(cnf); ++ ASN1_TYPE_free(atyp); + BIO_printf(bio_err, "ASN1_generate_nconf failed\n"); + goto end; + } +--- crypto/openssl/crypto/asn1/a_strex.c.orig ++++ crypto/openssl/crypto/asn1/a_strex.c +@@ -203,8 +203,10 @@ + orflags = CHARTYPE_LAST_ESC_2253; + if (type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; +- int utflen; +- utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ ++ if (utflen < 0) ++ return -1; /* error happened with UTF8 */ + for (i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly +--- crypto/openssl/crypto/bio/bf_lbuf.c.orig ++++ crypto/openssl/crypto/bio/bf_lbuf.c +@@ -191,14 +191,34 @@ + while (foundnl && inl > 0); + /* + * We've written as much as we can. The rest of the input buffer, if +- * any, is text that doesn't and with a NL and therefore needs to be +- * saved for the next trip. ++ * any, is text that doesn't end with a NL and therefore we need to try ++ * free up some space in our obuf so we can make forward progress. + */ +- if (inl > 0) { +- memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); +- ctx->obuf_len += inl; +- num += inl; ++ while (inl > 0) { ++ size_t avail = (size_t)ctx->obuf_size - (size_t)ctx->obuf_len; ++ size_t to_copy; ++ ++ if (avail == 0) { ++ /* Flush buffered data to make room */ ++ i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); ++ if (i <= 0) { ++ BIO_copy_next_retry(b); ++ return num > 0 ? num : i; ++ } ++ if (i < ctx->obuf_len) ++ memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); ++ ctx->obuf_len -= i; ++ continue; ++ } ++ ++ to_copy = inl > (int)avail ? avail : (size_t)inl; ++ memcpy(&(ctx->obuf[ctx->obuf_len]), in, to_copy); ++ ctx->obuf_len += (int)to_copy; ++ in += to_copy; ++ inl -= (int)to_copy; ++ num += (int)to_copy; + } ++ + return num; + } + +--- crypto/openssl/crypto/modes/ocb128.c.orig ++++ crypto/openssl/crypto/modes/ocb128.c +@@ -342,7 +342,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -356,6 +356,9 @@ + ctx->stream(in, out, num_blocks, ctx->keyenc, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + /* Loop through all full blocks to be encrypted */ + for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { +@@ -434,7 +437,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -448,6 +451,9 @@ + ctx->stream(in, out, num_blocks, ctx->keydec, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + OCB_BLOCK tmp; + +--- crypto/openssl/crypto/pkcs12/p12_decr.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_decr.c +@@ -88,6 +88,12 @@ + void *ret; + int outlen; + ++ if (oct == NULL) { ++ PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, ++ PKCS12_R_INVALID_NULL_ARGUMENT); ++ return NULL; ++ } ++ + if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length, + &out, &outlen, 0)) { + PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, +--- crypto/openssl/crypto/pkcs12/p12_kiss.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_kiss.c +@@ -183,11 +183,17 @@ + ASN1_BMPSTRING *fname = NULL; + ASN1_OCTET_STRING *lkid = NULL; + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) { ++ if (attrib->type != V_ASN1_BMPSTRING) ++ return 0; + fname = attrib->value.bmpstring; ++ } + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) { ++ if (attrib->type != V_ASN1_OCTET_STRING) ++ return 0; + lkid = attrib->value.octet_string; ++ } + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: +--- crypto/openssl/crypto/pkcs12/p12_utl.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_utl.c +@@ -207,6 +207,11 @@ + /* re-run the loop emitting UTF-8 string */ + for (asclen = 0, i = 0; i < unilen; ) { + j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i); ++ /* when UTF8_putc fails */ ++ if (j < 0) { ++ OPENSSL_free(asctmp); ++ return NULL; ++ } + if (j == 4) i += 4; + else i += 2; + asclen += j; +--- crypto/openssl/crypto/pkcs7/pk7_doit.c.orig ++++ crypto/openssl/crypto/pkcs7/pk7_doit.c +@@ -1092,6 +1092,8 @@ + ASN1_TYPE *astype; + if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL) + return NULL; ++ if (astype->type != V_ASN1_OCTET_STRING) ++ return NULL; + return astype->value.octet_string; + } + +--- crypto/openssl/crypto/ts/ts_rsp_verify.c.orig ++++ crypto/openssl/crypto/ts/ts_rsp_verify.c +@@ -262,7 +262,7 @@ + ASN1_TYPE *attr; + const unsigned char *p; + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); +- if (!attr) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); +@@ -274,7 +274,7 @@ + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); +- if (attr == NULL) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); +-- diff --git a/website/static/security/patches/SA-26:01/openssl-13.patch.asc b/website/static/security/patches/SA-26:01/openssl-13.patch.asc new file mode 100644 index 0000000000..306b97c814 --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDUACgkQbljekB8A +Gu/wRRAAsRtcHehErSu5h3CJGuNI0jergHNiu3CxKvBZAeBzLm0Me7SPifv/zgjd +WnyorGyaohhaCGXubANH/64qSge7gDFQBm9v99uI/rkRUsQvsSQf78GeGnf3ssBA +GgLrWkO4Hp0QoA7H0n0lvi4IX97c6qXKm4hR7YyhBHkxHIrq9Qk8pjibQSjbfGkD +0y7Y4OQ+sXUtAazfTBzXJNdWnAWgWqQZcJCEEilc8DnG0/VW16sMMh/vAUF8aYuG +0V6V0Ml1/n24klbnOC062AFX2oDuUodwxUiYEnwGz9VhLjeCxXUXWghhkQ9BLr9H +lld805CT/fDqkPOXkxyt/UJ95p0JuCV4RPyrRupGIg/OZDrOQ2iJ55Xi+NaJHPYM +S+cIPIsfHEVY7t2BNdb2ZCXwtd0CFyKdCwwu7tP7+yD6B3Ju09UvmsrfBFMSQw1c +hOZpww6/vXrQXzUaIdyBF/VV+8gFNsAIh6baYEjiLXHn7pmGGac4fCQM7OsOMbhc +WpZ7vkqPFFQYGsKbnTCZ82AjjsYPotdIWn8hlLqkHD0ZlbUptl65CpS+hPYaDSnV +4S94M6Aof0UhGPeLrSdq+IApkTAXmihWu4HSG7oG+n1f48ZkfgmQiMd1PmQAZYey +zSb+r3p8Dc1cbFz+a5saH/GuNdnZEkrXJQgWx5PiwMIShKEBCLs= +=7Bwk +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:01/openssl-14.patch b/website/static/security/patches/SA-26:01/openssl-14.patch new file mode 100644 index 0000000000..cd1b9214d3 --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-14.patch @@ -0,0 +1,251 @@ +--- crypto/openssl/apps/s_client.c.orig ++++ crypto/openssl/apps/s_client.c +@@ -2650,8 +2650,9 @@ + goto end; + } + atyp = ASN1_generate_nconf(genstr, cnf); +- if (atyp == NULL) { ++ if (atyp == NULL || atyp->type != V_ASN1_SEQUENCE) { + NCONF_free(cnf); ++ ASN1_TYPE_free(atyp); + BIO_printf(bio_err, "ASN1_generate_nconf failed\n"); + goto end; + } +--- crypto/openssl/crypto/asn1/a_strex.c.orig ++++ crypto/openssl/crypto/asn1/a_strex.c +@@ -204,8 +204,10 @@ + orflags = CHARTYPE_LAST_ESC_2253; + if (type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; +- int utflen; +- utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ ++ if (utflen < 0) ++ return -1; /* error happened with UTF8 */ + for (i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly +--- crypto/openssl/crypto/asn1/evp_asn1.c.orig ++++ crypto/openssl/crypto/asn1/evp_asn1.c +@@ -60,6 +60,12 @@ + oct->flags = 0; + } + ++/* ++ * This function copies 'anum' to 'num' and the data of 'oct' to 'data'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum, + long *num, unsigned char *data, int max_len) + { +@@ -106,6 +112,13 @@ + return 0; + } + ++/* ++ * This function decodes an int-octet sequence and copies the integer to 'num' ++ * and the data of octet to 'data'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) + { +@@ -162,6 +175,13 @@ + return 0; + } + ++/* ++ * This function decodes an octet-int sequence and copies the data of octet ++ * to 'data' and the integer to 'num'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) + { +--- crypto/openssl/crypto/bio/bf_lbuf.c.orig ++++ crypto/openssl/crypto/bio/bf_lbuf.c +@@ -189,14 +189,34 @@ + while (foundnl && inl > 0); + /* + * We've written as much as we can. The rest of the input buffer, if +- * any, is text that doesn't and with a NL and therefore needs to be +- * saved for the next trip. ++ * any, is text that doesn't end with a NL and therefore we need to try ++ * free up some space in our obuf so we can make forward progress. + */ +- if (inl > 0) { +- memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); +- ctx->obuf_len += inl; +- num += inl; ++ while (inl > 0) { ++ size_t avail = (size_t)ctx->obuf_size - (size_t)ctx->obuf_len; ++ size_t to_copy; ++ ++ if (avail == 0) { ++ /* Flush buffered data to make room */ ++ i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); ++ if (i <= 0) { ++ BIO_copy_next_retry(b); ++ return num > 0 ? num : i; ++ } ++ if (i < ctx->obuf_len) ++ memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); ++ ctx->obuf_len -= i; ++ continue; ++ } ++ ++ to_copy = inl > (int)avail ? avail : (size_t)inl; ++ memcpy(&(ctx->obuf[ctx->obuf_len]), in, to_copy); ++ ctx->obuf_len += (int)to_copy; ++ in += to_copy; ++ inl -= (int)to_copy; ++ num += (int)to_copy; + } ++ + return num; + } + +--- crypto/openssl/crypto/evp/evp_lib.c.orig ++++ crypto/openssl/crypto/evp/evp_lib.c +@@ -249,10 +249,9 @@ + if (type == NULL || asn1_params == NULL) + return 0; + +- i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH); +- if (i <= 0) ++ i = ossl_asn1_type_get_octetstring_int(type, &tl, iv, EVP_MAX_IV_LENGTH); ++ if (i <= 0 || i > EVP_MAX_IV_LENGTH) + return -1; +- ossl_asn1_type_get_octetstring_int(type, &tl, iv, i); + + memcpy(asn1_params->iv, iv, i); + asn1_params->iv_len = i; +--- crypto/openssl/crypto/modes/ocb128.c.orig ++++ crypto/openssl/crypto/modes/ocb128.c +@@ -342,7 +342,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -356,6 +356,9 @@ + ctx->stream(in, out, num_blocks, ctx->keyenc, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + /* Loop through all full blocks to be encrypted */ + for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { +@@ -434,7 +437,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -448,6 +451,9 @@ + ctx->stream(in, out, num_blocks, ctx->keydec, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + OCB_BLOCK tmp; + +--- crypto/openssl/crypto/pkcs12/p12_decr.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_decr.c +@@ -137,6 +137,11 @@ + void *ret; + int outlen = 0; + ++ if (oct == NULL) { ++ ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER); ++ return NULL; ++ } ++ + if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length, + &out, &outlen, 0, libctx, propq)) + return NULL; +--- crypto/openssl/crypto/pkcs12/p12_kiss.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_kiss.c +@@ -190,11 +190,17 @@ + ASN1_BMPSTRING *fname = NULL; + ASN1_OCTET_STRING *lkid = NULL; + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) { ++ if (attrib->type != V_ASN1_BMPSTRING) ++ return 0; + fname = attrib->value.bmpstring; ++ } + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) { ++ if (attrib->type != V_ASN1_OCTET_STRING) ++ return 0; + lkid = attrib->value.octet_string; ++ } + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: +--- crypto/openssl/crypto/pkcs12/p12_utl.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_utl.c +@@ -212,6 +212,11 @@ + /* re-run the loop emitting UTF-8 string */ + for (asclen = 0, i = 0; i < unilen; ) { + j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i); ++ /* when UTF8_putc fails */ ++ if (j < 0) { ++ OPENSSL_free(asctmp); ++ return NULL; ++ } + if (j == 4) i += 4; + else i += 2; + asclen += j; +--- crypto/openssl/crypto/pkcs7/pk7_doit.c.orig ++++ crypto/openssl/crypto/pkcs7/pk7_doit.c +@@ -1182,6 +1182,8 @@ + ASN1_TYPE *astype; + if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL) + return NULL; ++ if (astype->type != V_ASN1_OCTET_STRING) ++ return NULL; + return astype->value.octet_string; + } + +--- crypto/openssl/crypto/ts/ts_rsp_verify.c.orig ++++ crypto/openssl/crypto/ts/ts_rsp_verify.c +@@ -209,7 +209,7 @@ + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); +- if (attr == NULL) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); +@@ -222,7 +222,7 @@ + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); +- if (attr == NULL) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); +-- diff --git a/website/static/security/patches/SA-26:01/openssl-14.patch.asc b/website/static/security/patches/SA-26:01/openssl-14.patch.asc new file mode 100644 index 0000000000..a4f54c7dc5 --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDYACgkQbljekB8A +Gu+XhQ//VlCelzAFBR9vtJqVyKb0vfoT3grP2HnboOEcZaQY4Uekddk0JiNqUOwp +p2f1fcLnsSqoEcMmzQXK5qD/ExN2dhhKFO+psrIv3StDXrbcfYVVOjhpn72GjrjU +UxjjA7FF4MzmF3VERZqMauThDkT9699YwpSJI2HO9FO7NEj3ZQcB/+T0mH0dU8Nv +/OwVghhXYrEzggjg9f7/TIfW5KgCdh2LtpXZkTmsyK1d39mHxhvobhQD6Jy9hTMc +AELr8dmD4slAyw+PLUc9zZX12DlARVAE0UXkJgTknPYN6zfTeCqBqSQe37U6yk4O +ec1jguNEmRvy8B594O/dZnyqa2BgA4k3qBRdCt+YfOMPk3Dq0cdLt6zWhy6aK937 +l4qD7890uWQo+y3H+gcPm6zm+ivYhSuFePKpZ8iVmA1+8bJD7+8AveiBOIXcEYL8 +ctfcqdLj4uOjL+Fipa7TeLS0y5lA8FcjntT8tLrd2ax0UODvnNXGzGawk3Oot7y2 +W5+vChdA83GyaoaPCNXN7Qh7IJxfWBEq5byQk1vTMZ8Tp4dBmr3qc6MQG74QX6Wb +FZXOxFwKVor8S90LbuOcGSdJIividxBp0N/koazNR5SXtNGI6a7THBgnx2ownPOt +QCh5gOji+ue8nLLSJIfSYHUKupP9ZBSY6Okwzmr4suavdMr282I= +=PsKm +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:01/openssl-15.patch b/website/static/security/patches/SA-26:01/openssl-15.patch new file mode 100644 index 0000000000..b8c4378a0b --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-15.patch @@ -0,0 +1,550 @@ +--- crypto/openssl/apps/dgst.c.orig ++++ crypto/openssl/apps/dgst.c +@@ -704,12 +704,11 @@ + { + int res, ret = EXIT_FAILURE; + size_t len = 0; +- int buflen = 0; +- int maxlen = 16 * 1024 * 1024; ++ size_t buflen = 0; ++ size_t maxlen = 16 * 1024 * 1024; + uint8_t *buf = NULL, *sig = NULL; + +- buflen = bio_to_mem(&buf, maxlen, in); +- if (buflen <= 0) { ++ if (!bio_to_mem(&buf, &buflen, maxlen, in)) { + BIO_printf(bio_err, "Read error in %s\n", file); + return ret; + } +--- crypto/openssl/apps/include/apps.h.orig ++++ crypto/openssl/apps/include/apps.h +@@ -253,7 +253,7 @@ + X509_NAME *parse_name(const char *str, int chtype, int multirdn, + const char *desc); + void policies_print(X509_STORE_CTX *ctx); +-int bio_to_mem(unsigned char **out, int maxlen, BIO *in); ++int bio_to_mem(unsigned char **out, size_t *outlen, size_t maxlen, BIO *in); + int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); + int x509_ctrl_string(X509 *x, const char *value); + int x509_req_ctrl_string(X509_REQ *x, const char *value); +--- crypto/openssl/apps/lib/apps.c.orig ++++ crypto/openssl/apps/lib/apps.c +@@ -49,6 +49,7 @@ + #include "apps.h" + + #include "internal/sockets.h" /* for openssl_fdset() */ ++#include "internal/numbers.h" /* for LONG_MAX */ + #include "internal/e_os.h" + + #ifdef _WIN32 +@@ -2010,45 +2011,45 @@ + } + + /* +- * Read whole contents of a BIO into an allocated memory buffer and return +- * it. ++ * Read whole contents of a BIO into an allocated memory buffer. ++ * The return value is one on success, zero on error. ++ * If `maxlen` is non-zero, at most `maxlen` bytes are returned, or else, if ++ * the input is longer than `maxlen`, an error is returned. ++ * If `maxlen` is zero, the limit is effectively `SIZE_MAX`. + */ +- +-int bio_to_mem(unsigned char **out, int maxlen, BIO *in) ++int bio_to_mem(unsigned char **out, size_t *outlen, size_t maxlen, BIO *in) + { ++ unsigned char tbuf[4096]; + BIO *mem; +- int len, ret; +- unsigned char tbuf[1024]; ++ BUF_MEM *bufm; ++ size_t sz = 0; ++ int len; + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) +- return -1; ++ return 0; + for (;;) { +- if ((maxlen != -1) && maxlen < 1024) +- len = maxlen; +- else +- len = 1024; +- len = BIO_read(in, tbuf, len); +- if (len < 0) { +- BIO_free(mem); +- return -1; +- } +- if (len == 0) ++ if ((len = BIO_read(in, tbuf, 4096)) == 0) + break; +- if (BIO_write(mem, tbuf, len) != len) { ++ if (len < 0 ++ || BIO_write(mem, tbuf, len) != len ++ || sz > SIZE_MAX - len ++ || ((sz += len) > maxlen && maxlen != 0)) { + BIO_free(mem); +- return -1; ++ return 0; + } +- if (maxlen != -1) +- maxlen -= len; +- +- if (maxlen == 0) +- break; + } +- ret = BIO_get_mem_data(mem, (char **)out); +- BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); ++ ++ /* So BIO_free orphans BUF_MEM */ ++ (void)BIO_set_close(mem, BIO_NOCLOSE); ++ BIO_get_mem_ptr(mem, &bufm); + BIO_free(mem); +- return ret; ++ *out = (unsigned char *)bufm->data; ++ *outlen = bufm->length; ++ /* Tell BUF_MEM to orphan data */ ++ bufm->data = NULL; ++ BUF_MEM_free(bufm); ++ return 1; + } + + int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) +--- crypto/openssl/apps/pkeyutl.c.orig ++++ crypto/openssl/apps/pkeyutl.c +@@ -40,7 +40,7 @@ + + static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, + EVP_PKEY *pkey, BIO *in, +- int filesize, unsigned char *sig, int siglen, ++ int filesize, unsigned char *sig, size_t siglen, + unsigned char **out, size_t *poutlen); + + static int only_nomd(EVP_PKEY *pkey) +@@ -133,7 +133,7 @@ + char hexdump = 0, asn1parse = 0, rev = 0, *prog; + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL, *secret = NULL; + OPTION_CHOICE o; +- int buf_inlen = 0, siglen = -1; ++ size_t buf_inlen = 0, siglen = 0; + int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF; + int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; + int engine_impl = 0; +@@ -486,31 +486,31 @@ + + if (sigfile != NULL) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); ++ size_t maxsiglen = 16 * 1024 * 1024; + + if (sigbio == NULL) { + BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); + goto end; + } +- siglen = bio_to_mem(&sig, keysize * 10, sigbio); +- BIO_free(sigbio); +- if (siglen < 0) { ++ if (!bio_to_mem(&sig, &siglen, maxsiglen, sigbio)) { ++ BIO_free(sigbio); + BIO_printf(bio_err, "Error reading signature data\n"); + goto end; + } ++ BIO_free(sigbio); + } + + /* Raw input data is handled elsewhere */ + if (in != NULL && !rawin) { + /* Read the input data */ +- buf_inlen = bio_to_mem(&buf_in, -1, in); +- if (buf_inlen < 0) { ++ if (!bio_to_mem(&buf_in, &buf_inlen, 0, in)) { + BIO_printf(bio_err, "Error reading input Data\n"); + goto end; + } + if (rev) { + size_t i; + unsigned char ctmp; +- size_t l = (size_t)buf_inlen; ++ size_t l = buf_inlen; + + for (i = 0; i < l / 2; i++) { + ctmp = buf_in[i]; +@@ -525,7 +525,8 @@ + && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) { + if (buf_inlen > EVP_MAX_MD_SIZE) { + BIO_printf(bio_err, +- "Error: The non-raw input data length %d is too long - max supported hashed size is %d\n", ++ "Error: The non-raw input data length %zd is too long - " ++ "max supported hashed size is %d\n", + buf_inlen, EVP_MAX_MD_SIZE); + goto end; + } +@@ -536,8 +537,7 @@ + rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen, + NULL, 0); + } else { +- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, +- buf_in, (size_t)buf_inlen); ++ rv = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen); + } + if (rv == 1) { + BIO_puts(out, "Signature Verified Successfully\n"); +@@ -556,8 +556,8 @@ + buf_outlen = kdflen; + rv = 1; + } else { +- rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen, NULL, (size_t *)&secretlen); ++ rv = do_keyop(ctx, pkey_op, NULL, &buf_outlen, ++ buf_in, buf_inlen, NULL, &secretlen); + } + if (rv > 0 + && (secretlen > 0 || (pkey_op != EVP_PKEY_OP_ENCAPSULATE +@@ -568,8 +568,8 @@ + if (secretlen > 0) + secret = app_malloc(secretlen, "secret output"); + rv = do_keyop(ctx, pkey_op, +- buf_out, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen, secret, (size_t *)&secretlen); ++ buf_out, &buf_outlen, ++ buf_in, buf_inlen, secret, &secretlen); + } + } + if (rv <= 0) { +@@ -838,7 +838,7 @@ + + static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, + EVP_PKEY *pkey, BIO *in, +- int filesize, unsigned char *sig, int siglen, ++ int filesize, unsigned char *sig, size_t siglen, + unsigned char **out, size_t *poutlen) + { + int rv = 0; +@@ -861,7 +861,7 @@ + BIO_printf(bio_err, "Error reading raw input data\n"); + goto end; + } +- rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len); ++ rv = EVP_DigestVerify(mctx, sig, siglen, mbuf, buf_len); + break; + case EVP_PKEY_OP_SIGN: + buf_len = BIO_read(in, mbuf, filesize); +@@ -895,7 +895,7 @@ + goto end; + } + } +- rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen); ++ rv = EVP_DigestVerifyFinal(mctx, sig, siglen); + break; + case EVP_PKEY_OP_SIGN: + for (;;) { +--- crypto/openssl/apps/s_client.c.orig ++++ crypto/openssl/apps/s_client.c +@@ -2834,8 +2834,9 @@ + goto end; + } + atyp = ASN1_generate_nconf(genstr, cnf); +- if (atyp == NULL) { ++ if (atyp == NULL || atyp->type != V_ASN1_SEQUENCE) { + NCONF_free(cnf); ++ ASN1_TYPE_free(atyp); + BIO_printf(bio_err, "ASN1_generate_nconf failed\n"); + goto end; + } +--- crypto/openssl/crypto/asn1/a_strex.c.orig ++++ crypto/openssl/crypto/asn1/a_strex.c +@@ -204,8 +204,10 @@ + orflags = CHARTYPE_LAST_ESC_2253; + if (type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; +- int utflen; +- utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); ++ ++ if (utflen < 0) ++ return -1; /* error happened with UTF8 */ + for (i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly +--- crypto/openssl/crypto/asn1/evp_asn1.c.orig ++++ crypto/openssl/crypto/asn1/evp_asn1.c +@@ -60,6 +60,12 @@ + oct->flags = 0; + } + ++/* ++ * This function copies 'anum' to 'num' and the data of 'oct' to 'data'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum, + long *num, unsigned char *data, int max_len) + { +@@ -106,6 +112,13 @@ + return 0; + } + ++/* ++ * This function decodes an int-octet sequence and copies the integer to 'num' ++ * and the data of octet to 'data'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) + { +@@ -162,6 +175,13 @@ + return 0; + } + ++/* ++ * This function decodes an octet-int sequence and copies the data of octet ++ * to 'data' and the integer to 'num'. ++ * If the length of 'data' > 'max_len', copies only the first 'max_len' ++ * bytes, but returns the full length of 'oct'; this allows distinguishing ++ * whether all the data was copied. ++ */ + int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) + { +--- crypto/openssl/crypto/bio/bf_lbuf.c.orig ++++ crypto/openssl/crypto/bio/bf_lbuf.c +@@ -186,14 +186,34 @@ + while (foundnl && inl > 0); + /* + * We've written as much as we can. The rest of the input buffer, if +- * any, is text that doesn't and with a NL and therefore needs to be +- * saved for the next trip. ++ * any, is text that doesn't end with a NL and therefore we need to try ++ * free up some space in our obuf so we can make forward progress. + */ +- if (inl > 0) { +- memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); +- ctx->obuf_len += inl; +- num += inl; ++ while (inl > 0) { ++ size_t avail = (size_t)ctx->obuf_size - (size_t)ctx->obuf_len; ++ size_t to_copy; ++ ++ if (avail == 0) { ++ /* Flush buffered data to make room */ ++ i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); ++ if (i <= 0) { ++ BIO_copy_next_retry(b); ++ return num > 0 ? num : i; ++ } ++ if (i < ctx->obuf_len) ++ memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); ++ ctx->obuf_len -= i; ++ continue; ++ } ++ ++ to_copy = inl > (int)avail ? avail : (size_t)inl; ++ memcpy(&(ctx->obuf[ctx->obuf_len]), in, to_copy); ++ ctx->obuf_len += (int)to_copy; ++ in += to_copy; ++ inl -= (int)to_copy; ++ num += (int)to_copy; + } ++ + return num; + } + +--- crypto/openssl/crypto/evp/evp_lib.c.orig ++++ crypto/openssl/crypto/evp/evp_lib.c +@@ -228,10 +228,9 @@ + if (type == NULL || asn1_params == NULL) + return 0; + +- i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH); +- if (i <= 0) ++ i = ossl_asn1_type_get_octetstring_int(type, &tl, iv, EVP_MAX_IV_LENGTH); ++ if (i <= 0 || i > EVP_MAX_IV_LENGTH) + return -1; +- ossl_asn1_type_get_octetstring_int(type, &tl, iv, i); + + memcpy(asn1_params->iv, iv, i); + asn1_params->iv_len = i; +--- crypto/openssl/crypto/modes/ocb128.c.orig ++++ crypto/openssl/crypto/modes/ocb128.c +@@ -338,7 +338,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -352,6 +352,9 @@ + ctx->stream(in, out, num_blocks, ctx->keyenc, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + /* Loop through all full blocks to be encrypted */ + for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { +@@ -430,7 +433,7 @@ + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { +- size_t max_idx = 0, top = (size_t)all_num_blocks; ++ size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; + + /* + * See how many L_{i} entries we need to process data at hand +@@ -444,6 +447,9 @@ + ctx->stream(in, out, num_blocks, ctx->keydec, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); ++ processed_bytes = num_blocks * 16; ++ in += processed_bytes; ++ out += processed_bytes; + } else { + OCB_BLOCK tmp; + +--- crypto/openssl/crypto/pkcs12/p12_decr.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_decr.c +@@ -143,6 +143,11 @@ + void *ret; + int outlen = 0; + ++ if (oct == NULL) { ++ ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER); ++ return NULL; ++ } ++ + if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length, + &out, &outlen, 0, libctx, propq)) + return NULL; +--- crypto/openssl/crypto/pkcs12/p12_kiss.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_kiss.c +@@ -197,11 +197,17 @@ + ASN1_BMPSTRING *fname = NULL; + ASN1_OCTET_STRING *lkid = NULL; + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) { ++ if (attrib->type != V_ASN1_BMPSTRING) ++ return 0; + fname = attrib->value.bmpstring; ++ } + +- if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) ++ if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) { ++ if (attrib->type != V_ASN1_OCTET_STRING) ++ return 0; + lkid = attrib->value.octet_string; ++ } + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: +--- crypto/openssl/crypto/pkcs12/p12_mutl.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_mutl.c +@@ -122,8 +122,6 @@ + ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED); + goto err; + } +- keylen = ASN1_INTEGER_get(pbkdf2_param->keylength); +- pbkdf2_salt = pbkdf2_param->salt->value.octet_string; + + if (pbkdf2_param->prf == NULL) { + kdf_hmac_nid = NID_hmacWithSHA1; +@@ -138,6 +136,22 @@ + goto err; + } + ++ /* Validate salt is an OCTET STRING choice */ ++ if (pbkdf2_param->salt == NULL ++ || pbkdf2_param->salt->type != V_ASN1_OCTET_STRING) { ++ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR); ++ goto err; ++ } ++ pbkdf2_salt = pbkdf2_param->salt->value.octet_string; ++ ++ /* RFC 9579 specifies missing key length as invalid */ ++ if (pbkdf2_param->keylength != NULL) ++ keylen = ASN1_INTEGER_get(pbkdf2_param->keylength); ++ if (keylen <= 0 || keylen > EVP_MAX_MD_SIZE) { ++ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR); ++ goto err; ++ } ++ + if (PKCS5_PBKDF2_HMAC(pass, passlen, pbkdf2_salt->data, pbkdf2_salt->length, + ASN1_INTEGER_get(pbkdf2_param->iter), kdf_md, keylen, key) <= 0) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR); +--- crypto/openssl/crypto/pkcs12/p12_utl.c.orig ++++ crypto/openssl/crypto/pkcs12/p12_utl.c +@@ -206,6 +206,11 @@ + /* re-run the loop emitting UTF-8 string */ + for (asclen = 0, i = 0; i < unilen; ) { + j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i); ++ /* when UTF8_putc fails */ ++ if (j < 0) { ++ OPENSSL_free(asctmp); ++ return NULL; ++ } + if (j == 4) i += 4; + else i += 2; + asclen += j; +--- crypto/openssl/crypto/pkcs7/pk7_doit.c.orig ++++ crypto/openssl/crypto/pkcs7/pk7_doit.c +@@ -1231,6 +1231,8 @@ + ASN1_TYPE *astype; + if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL) + return NULL; ++ if (astype->type != V_ASN1_OCTET_STRING) ++ return NULL; + return astype->value.octet_string; + } + +--- crypto/openssl/crypto/ts/ts_rsp_verify.c.orig ++++ crypto/openssl/crypto/ts/ts_rsp_verify.c +@@ -211,7 +211,7 @@ + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); +- if (attr == NULL) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); +@@ -224,7 +224,7 @@ + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); +- if (attr == NULL) ++ if (attr == NULL || attr->type != V_ASN1_SEQUENCE) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); +--- crypto/openssl/ssl/quic/quic_impl.c.orig ++++ crypto/openssl/ssl/quic/quic_impl.c +@@ -5065,6 +5065,8 @@ + { + const SSL_CIPHER *ciph = ssl3_get_cipher_by_char(p); + ++ if (ciph == NULL) ++ return NULL; + if ((ciph->algorithm2 & SSL_QUIC) == 0) + return NULL; + +--- crypto/openssl/ssl/statem/statem_lib.c.orig ++++ crypto/openssl/ssl/statem/statem_lib.c +@@ -2912,6 +2912,12 @@ + goto err; + } + ++ /* Prevent excessive pre-decompression allocation */ ++ if (expected_length > sc->max_cert_list) { ++ SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE); ++ goto err; ++ } ++ + if (PACKET_remaining(pkt) != comp_length || comp_length == 0) { + SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_DECOMPRESSION); + goto err; +-- diff --git a/website/static/security/patches/SA-26:01/openssl-15.patch.asc b/website/static/security/patches/SA-26:01/openssl-15.patch.asc new file mode 100644 index 0000000000..ed49341c69 --- /dev/null +++ b/website/static/security/patches/SA-26:01/openssl-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NDcACgkQbljekB8A +Gu+GLw/+M8A7WK1OFMauAqR7bPrcuztHRMZhAvKunM2jnjtiMRqLtQBeQYg6aeTR +sMUqm1R2NfD3ic5zt7kKTbPmHfG3TSCDglDfTiYiCAwzTEg9jsejg8Mqm64zDWf7 +/T+TXjzipdKYpasNAIZYmmvoeOtLNp5tzTOAOxPxwOunHiMxdezTV3Kb1JSH45A0 +QpbHYMYfPWREOChpJwzxDDjYdbtx+WDKH+V6ZEbAd495B8IlF7QajST6gfh2xZVo +/J5Iz1wqlQbasy2G2eaoBU2zBMzvZUpNpiodw2S3qV95aZ2gSKO7swTkV7Qg/3/t +lBdljQNrMPWxwTP85s1E+iK74wS2VOej1iQsuBiX024ErDUo4u8hB9be9sYwGhkH +1RS5f0P3SvH1QGwBQ0nwaoxGz0RHIpb4kS7I//PWz8mD74e8g6xXm8/0r/mEoptm +Rp18d7VuAYMhSbK39jJEax+Ud6f/PyRR+lMSvi+EZ9BeurxFR5hXAVOu35OYwgzH +44j09SqHPq+m0zv7DDb2/fkh/+j3D5GwqVA3ykEiZX6Wgf+e36IFgJOxzz6BiKq1 +dCmJxXwSKPN1pFc7uqupUpDyGFOoXMCkcflOA4ZOhxcfYoF14oKnaGdqmQXrYGGv +zFPjHG7YOd+W0DN2GSTJfiaAtYtBaTFNHBxeoKIAyFc0SVvVYQ8= +=rFjZ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:02/jail-13.patch b/website/static/security/patches/SA-26:02/jail-13.patch new file mode 100644 index 0000000000..43bac1e9a4 --- /dev/null +++ b/website/static/security/patches/SA-26:02/jail-13.patch @@ -0,0 +1,550 @@ +--- sys/fs/cd9660/cd9660_lookup.c.orig ++++ sys/fs/cd9660/cd9660_lookup.c +@@ -134,7 +134,7 @@ + char *name; + struct vnode **vpp = ap->a_vpp; + struct componentname *cnp = ap->a_cnp; +- int flags = cnp->cn_flags; ++ uint64_t flags = cnp->cn_flags; + int nameiop = cnp->cn_nameiop; + + ep2 = ep = NULL; +--- sys/fs/fuse/fuse_vnops.c.orig ++++ sys/fs/fuse/fuse_vnops.c +@@ -1433,9 +1433,9 @@ + struct timespec now; + + int nameiop = cnp->cn_nameiop; +- int flags = cnp->cn_flags; +- int wantparent = flags & (LOCKPARENT | WANTPARENT); +- int islastcn = flags & ISLASTCN; ++ bool wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); ++ bool isdotdot = cnp->cn_flags & ISDOTDOT; ++ bool islastcn = cnp->cn_flags & ISLASTCN; + struct mount *mp = vnode_mount(dvp); + struct fuse_data *data = fuse_get_mpdata(mp); + int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS; +@@ -1468,8 +1468,7 @@ + return err; + + is_dot = cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.'; +- if ((flags & ISDOTDOT) && !(data->dataflags & FSESS_EXPORT_SUPPORT)) +- { ++ if (isdotdot && !(data->dataflags & FSESS_EXPORT_SUPPORT)) { + if (!(VTOFUD(dvp)->flag & FN_PARENT_NID)) { + /* + * Since the file system doesn't support ".." lookups, +@@ -1590,7 +1589,7 @@ + } + } else { + /* Entry was found */ +- if (flags & ISDOTDOT) { ++ if (isdotdot) { + struct fuse_lookup_alloc_arg flaa; + + flaa.nid = nid; +--- sys/fs/nullfs/null_vnops.c.orig ++++ sys/fs/nullfs/null_vnops.c +@@ -389,7 +389,7 @@ + { + struct componentname *cnp = ap->a_cnp; + struct vnode *dvp = ap->a_dvp; +- int flags = cnp->cn_flags; ++ uint64_t flags = cnp->cn_flags; + struct vnode *vp, *ldvp, *lvp; + struct mount *mp; + int error; +@@ -407,17 +407,25 @@ + + /* + * Renames in the lower mounts might create an inconsistent +- * configuration where lower vnode is moved out of the +- * directory tree remounted by our null mount. Do not try to +- * handle it fancy, just avoid VOP_LOOKUP() with DOTDOT name +- * which cannot be handled by VOP, at least passing over lower +- * root. ++ * configuration where lower vnode is moved out of the directory tree ++ * remounted by our null mount. ++ * ++ * Do not try to handle it fancy, just avoid VOP_LOOKUP() with DOTDOT ++ * name which cannot be handled by the VOP. + */ +- if ((ldvp->v_vflag & VV_ROOT) != 0 && (flags & ISDOTDOT) != 0) { +- KASSERT((dvp->v_vflag & VV_ROOT) == 0, +- ("ldvp %p fl %#x dvp %p fl %#x flags %#x", +- ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, flags)); +- return (ENOENT); ++ if ((flags & ISDOTDOT) != 0) { ++ struct nameidata *ndp; ++ ++ if ((ldvp->v_vflag & VV_ROOT) != 0) { ++ KASSERT((dvp->v_vflag & VV_ROOT) == 0, ++ ("ldvp %p fl %#x dvp %p fl %#x flags %#jx", ++ ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, ++ (uintmax_t)flags)); ++ return (ENOENT); ++ } ++ ndp = lookup_nameidata(cnp); ++ if (ndp != NULL && lookup_isroot(ndp, ldvp)) ++ return (ENOENT); + } + + /* +--- sys/fs/smbfs/smbfs_vnops.c.orig ++++ sys/fs/smbfs/smbfs_vnops.c +@@ -1044,7 +1044,7 @@ + struct smbfattr fattr, *fap; + struct smb_cred *scred; + char *name = cnp->cn_nameptr; +- int flags = cnp->cn_flags; ++ uint64_t flags = cnp->cn_flags; + int nameiop = cnp->cn_nameiop; + int nmlen = cnp->cn_namelen; + int error, islastcn, isdot; +--- sys/fs/unionfs/union_vnops.c.orig ++++ sys/fs/unionfs/union_vnops.c +@@ -76,14 +76,30 @@ + KASSERT(((vp)->v_op == &unionfs_vnodeops), \ + ("unionfs: it is not unionfs-vnode")) + ++static bool ++unionfs_lookup_isroot(struct componentname *cnp, struct vnode *dvp) ++{ ++ struct nameidata *ndp; ++ ++ if (dvp == NULL) ++ return (false); ++ if ((dvp->v_vflag & VV_ROOT) != 0) ++ return (true); ++ ndp = lookup_nameidata(cnp); ++ if (ndp == NULL) ++ return (false); ++ return (lookup_isroot(ndp, dvp)); ++} ++ + static int + unionfs_lookup(struct vop_cachedlookup_args *ap) + { + int iswhiteout; + int lockflag; + int error , uerror, lerror; ++ uint64_t cnflags; + u_long nameiop; +- u_long cnflags, cnflagsbk; ++ u_long cnflagsbk; + struct unionfs_node *dunp; + struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp; + struct vattr va; +@@ -124,6 +140,10 @@ + if (LOOKUP != nameiop && udvp == NULLVP) + return (EROFS); + ++ if (unionfs_lookup_isroot(cnp, udvp) || ++ unionfs_lookup_isroot(cnp, ldvp)) ++ return (ENOENT); ++ + if (udvp != NULLVP) { + dtmpvp = udvp; + if (ldvp != NULLVP) +--- sys/kern/uipc_mqueue.c.orig ++++ sys/kern/uipc_mqueue.c +@@ -846,7 +846,8 @@ + struct mqfs_node *pd; + struct mqfs_node *pn; + struct mqfs_info *mqfs; +- int nameiop, flags, error, namelen; ++ uint64_t flags; ++ int nameiop, error, namelen; + char *pname; + struct thread *td; + +--- sys/kern/vfs_cache.c.orig ++++ sys/kern/vfs_cache.c +@@ -4006,7 +4006,7 @@ + */ + struct nameidata_outer { + size_t ni_pathlen; +- int cn_flags; ++ uint64_t cn_flags; + }; + + struct nameidata_saved { +@@ -4292,7 +4292,7 @@ + (NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \ + FAILIFEXISTS | FOLLOW | EMPTYPATH | LOCKSHARED | SAVENAME | SAVESTART | \ + WILLBEDIR | ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK | \ +- WANTIOCTLCAPS) ++ WANTIOCTLCAPS | NAMEILOOKUP) + + #define CACHE_FPL_INTERNAL_CN_FLAGS \ + (ISDOTDOT | MAKEENTRY | ISLASTCN) +@@ -5126,30 +5126,19 @@ + cache_fplookup_dotdot(struct cache_fpl *fpl) + { + struct nameidata *ndp; +- struct componentname *cnp; + struct namecache *ncp; + struct vnode *dvp; +- struct prison *pr; + u_char nc_flag; + + ndp = fpl->ndp; +- cnp = fpl->cnp; + dvp = fpl->dvp; + +- MPASS(cache_fpl_isdotdot(cnp)); ++ MPASS(cache_fpl_isdotdot(fpl->cnp)); + + /* + * XXX this is racy the same way regular lookup is + */ +- for (pr = cnp->cn_cred->cr_prison; pr != NULL; +- pr = pr->pr_parent) +- if (dvp == pr->pr_root) +- break; +- +- if (dvp == ndp->ni_rootdir || +- dvp == ndp->ni_topdir || +- dvp == rootvnode || +- pr != NULL) { ++ if (lookup_isroot(ndp, dvp)) { + fpl->tvp = dvp; + fpl->tvp_seqc = vn_seqc_read_any(dvp); + if (seqc_in_modify(fpl->tvp_seqc)) { +--- sys/kern/vfs_lookup.c.orig ++++ sys/kern/vfs_lookup.c +@@ -530,12 +530,12 @@ + cnp->cn_origflags = cnp->cn_flags; + #endif + ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; +- KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n", ++ KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x", + __func__, ndp->ni_resflags)); + KASSERT(cnp->cn_cred && td->td_proc, ("namei: bad cred/proc")); + KASSERT((cnp->cn_flags & NAMEI_INTERNAL_FLAGS) == 0, +- ("namei: unexpected flags: %" PRIx64 "\n", +- cnp->cn_flags & NAMEI_INTERNAL_FLAGS)); ++ ("namei: unexpected flags: %#jx", ++ (uintmax_t)(cnp->cn_flags & NAMEI_INTERNAL_FLAGS))); + if (cnp->cn_flags & NOCACHE) + KASSERT(cnp->cn_nameiop != LOOKUP, + ("%s: NOCACHE passed with LOOKUP", __func__)); +@@ -761,6 +761,31 @@ + _Static_assert(MAXNAMLEN == NAME_MAX, + "MAXNAMLEN and NAME_MAX have different values"); + ++ ++struct nameidata * ++lookup_nameidata(struct componentname *cnp) ++{ ++ if ((cnp->cn_flags & NAMEILOOKUP) == 0) ++ return (NULL); ++ return (__containerof(cnp, struct nameidata, ni_cnd)); ++} ++ ++/* ++ * Would a dotdot lookup relative to dvp cause this lookup to cross a jail or ++ * chroot boundary? ++ */ ++bool ++lookup_isroot(struct nameidata *ndp, struct vnode *dvp) ++{ ++ for (struct prison *pr = ndp->ni_cnd.cn_cred->cr_prison; pr != NULL; ++ pr = pr->pr_parent) { ++ if (dvp == pr->pr_root) ++ return (true); ++ } ++ return (dvp == ndp->ni_rootdir || dvp == ndp->ni_topdir || ++ dvp == rootvnode); ++} ++ + /* + * Search a pathname. + * This is a very central and rather complicated routine. +@@ -808,7 +833,6 @@ + struct vnode *dp = NULL; /* the directory we are searching */ + struct vnode *tdp; /* saved dp */ + struct mount *mp; /* mount table entry */ +- struct prison *pr; + size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */ + int docache; /* == 0 do not cache last component */ + int wantparent; /* 1 => wantparent or lockparent flag */ +@@ -1008,15 +1032,11 @@ + goto bad; + } + for (;;) { +- for (pr = cnp->cn_cred->cr_prison; pr != NULL; +- pr = pr->pr_parent) +- if (dp == pr->pr_root) +- break; +- bool isroot = dp == ndp->ni_rootdir || +- dp == ndp->ni_topdir || dp == rootvnode || +- pr != NULL; +- if (isroot && (ndp->ni_lcf & +- NI_LCF_STRICTRELATIVE) != 0) { ++ bool isroot; ++ ++ isroot = lookup_isroot(ndp, dp); ++ if (__predict_false(isroot && (ndp->ni_lcf & ++ NI_LCF_STRICTRELATIVE) != 0)) { + error = ENOTCAPABLE; + goto capdotdot; + } +--- sys/kern/vfs_vnops.c.orig ++++ sys/kern/vfs_vnops.c +@@ -195,21 +195,26 @@ + } + + static uint64_t +-open2nameif(int fmode, u_int vn_open_flags) ++open2nameif(int fmode, u_int vn_open_flags, uint64_t cn_flags) + { + uint64_t res; + +- res = ISOPEN | LOCKLEAF; ++ res = ISOPEN | LOCKLEAF | cn_flags; + if ((fmode & O_RESOLVE_BENEATH) != 0) + res |= RBENEATH; + if ((fmode & O_EMPTY_PATH) != 0) + res |= EMPTYPATH; ++ if ((fmode & O_NOFOLLOW) != 0) ++ res &= ~FOLLOW; + if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) + res |= AUDITVNODE1; ++ else ++ res &= ~AUDITVNODE1; + if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0) + res |= NOCAPCHECK; + if ((vn_open_flags & VN_OPEN_WANTIOCTLCAPS) != 0) + res |= WANTIOCTLCAPS; ++ + return (res); + } + +@@ -242,7 +247,9 @@ + return (EINVAL); + else if ((fmode & (O_CREAT | O_DIRECTORY)) == O_CREAT) { + ndp->ni_cnd.cn_nameiop = CREATE; +- ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); ++ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, ++ ndp->ni_cnd.cn_flags); ++ + /* + * Set NOCACHE to avoid flushing the cache when + * rolling in many files at once. +@@ -251,8 +258,8 @@ + * exist despite NOCACHE. + */ + ndp->ni_cnd.cn_flags |= LOCKPARENT | NOCACHE | NC_KEEPPOSENTRY; +- if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) +- ndp->ni_cnd.cn_flags |= FOLLOW; ++ if ((fmode & O_EXCL) != 0) ++ ndp->ni_cnd.cn_flags &= ~FOLLOW; + if ((vn_open_flags & VN_OPEN_INVFS) == 0) + bwillwrite(); + if ((error = namei(ndp)) != 0) +@@ -320,9 +327,8 @@ + } + } else { + ndp->ni_cnd.cn_nameiop = LOOKUP; +- ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); +- ndp->ni_cnd.cn_flags |= (fmode & O_NOFOLLOW) != 0 ? NOFOLLOW : +- FOLLOW; ++ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, ++ ndp->ni_cnd.cn_flags); + if ((fmode & FWRITE) == 0) + ndp->ni_cnd.cn_flags |= LOCKSHARED; + if ((error = namei(ndp)) != 0) +--- sys/sys/namei.h.orig ++++ sys/sys/namei.h +@@ -154,6 +154,7 @@ + #define LOCKSHARED 0x0100 /* Shared lock leaf */ + #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ + #define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */ ++#define NAMEILOOKUP 0x200000000ULL /* cnp is embedded in nameidata */ + #define MODMASK 0xf000001ffULL /* mask of operational modifiers */ + + /* +@@ -254,7 +255,7 @@ + NDINIT_PREFILL(_ndp); \ + NDINIT_DBG(_ndp); \ + _ndp->ni_cnd.cn_nameiop = op; \ +- _ndp->ni_cnd.cn_flags = flags; \ ++ _ndp->ni_cnd.cn_flags = (flags) | NAMEILOOKUP; \ + _ndp->ni_segflg = segflg; \ + _ndp->ni_dirp = namep; \ + _ndp->ni_dirfd = dirfd; \ +@@ -271,6 +272,7 @@ + filecaps_free(&_ndp->ni_filecaps); \ + _ndp->ni_resflags = 0; \ + _ndp->ni_startdir = NULL; \ ++ _ndp->ni_cnd.cn_flags &= ~NAMEI_INTERNAL_FLAGS; \ + } while (0) + + #define NDPREINIT(ndp) do { \ +@@ -312,6 +314,8 @@ + + int namei(struct nameidata *ndp); + int lookup(struct nameidata *ndp); ++bool lookup_isroot(struct nameidata *ndp, struct vnode *dvp); ++struct nameidata *lookup_nameidata(struct componentname *cnp); + int relookup(struct vnode *dvp, struct vnode **vpp, + struct componentname *cnp); + #endif +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -13,6 +13,7 @@ + ATF_TESTS_C+= kern_copyin + ATF_TESTS_C+= kern_descrip_test + ATF_TESTS_C+= fdgrowtable_test ++ATF_TESTS_C+= jail_lookup_root + ATF_TESTS_C+= kill_zombie + .if ${MK_OPENSSL} != "no" + ATF_TESTS_C+= ktls_test +@@ -58,6 +59,10 @@ + PROGS+= pdeathsig_helper + PROGS+= sendfile_helper + ++.PATH: ${SRCTOP}/sbin/mount ++SRCS.jail_lookup_root+= jail_lookup_root.c getmntopts.c ++CFLAGS.jail_lookup_root+= -I${SRCTOP}/sbin/mount ++LIBADD.jail_lookup_root+= jail util + CFLAGS.sys_getrandom+= -I${SRCTOP}/sys/contrib/zstd/lib + LIBADD.sys_getrandom+= zstd + LIBADD.sys_getrandom+= c +--- /dev/null ++++ tests/sys/kern/jail_lookup_root.c +@@ -0,0 +1,133 @@ ++/*- ++ * SPDX-License-Identifier: BSD-2-Clause ++ * ++ * Copyright (c) 2025 Mark Johnston <markj@FreeBSD.org> ++ */ ++ ++#include <sys/param.h> ++#include <sys/jail.h> ++#include <sys/mount.h> ++#include <sys/stat.h> ++ ++#include <err.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <jail.h> ++#include <mntopts.h> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include <atf-c.h> ++ ++static void ++mkdir_checked(const char *dir, mode_t mode) ++{ ++ int error; ++ ++ error = mkdir(dir, mode); ++ ATF_REQUIRE_MSG(error == 0 || errno == EEXIST, ++ "mkdir %s: %s", dir, strerror(errno)); ++} ++ ++static void __unused ++mount_nullfs(const char *dir, const char *target) ++{ ++ struct iovec *iov; ++ char errmsg[1024]; ++ int error, iovlen; ++ ++ iov = NULL; ++ iovlen = 0; ++ ++ build_iovec(&iov, &iovlen, __DECONST(char *, "fstype"), ++ __DECONST(char *, "nullfs"), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "fspath"), ++ __DECONST(char *, target), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "from"), ++ __DECONST(char *, dir), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "errmsg"), ++ errmsg, sizeof(errmsg)); ++ ++ errmsg[0] = '\0'; ++ error = nmount(iov, iovlen, 0); ++ ATF_REQUIRE_MSG(error == 0, "nmount: %s", ++ errmsg[0] != '\0' ? errmsg : strerror(errno)); ++ ++ free_iovec(&iov, &iovlen); ++} ++ ++ATF_TC_WITH_CLEANUP(jail_root); ++ATF_TC_HEAD(jail_root, tc) ++{ ++ atf_tc_set_md_var(tc, "require.user", "root"); ++} ++ATF_TC_BODY(jail_root, tc) ++{ ++ int error, fd, jid; ++ ++ mkdir_checked("./root", 0755); ++ mkdir_checked("./root/a", 0755); ++ mkdir_checked("./root/b", 0755); ++ mkdir_checked("./root/a/c", 0755); ++ ++ jid = jail_setv(JAIL_CREATE | JAIL_ATTACH, ++ "name", "nullfs_jail_root_test", ++ "allow.mount", "true", ++ "allow.mount.nullfs", "true", ++ "enforce_statfs", "1", ++ "path", "./root", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid >= 0, "jail_setv: %s", jail_errmsg); ++ ++ mount_nullfs("/a", "/b"); ++ ++ error = chdir("/b/c"); ++ ATF_REQUIRE(error == 0); ++ ++ error = rename("/a/c", "/c"); ++ ATF_REQUIRE(error == 0); ++ ++ /* Descending to the jail root should be ok. */ ++ error = chdir(".."); ++ ATF_REQUIRE(error == 0); ++ ++ /* Going beyond the root will trigger an error. */ ++ error = chdir(".."); ++ ATF_REQUIRE_ERRNO(ENOENT, error != 0); ++ fd = open("..", O_RDONLY | O_DIRECTORY); ++ ATF_REQUIRE_ERRNO(ENOENT, fd < 0); ++} ++ATF_TC_CLEANUP(jail_root, tc) ++{ ++ struct statfs fs; ++ fsid_t fsid; ++ int error, jid; ++ ++ error = statfs("./root/b", &fs); ++ if (error != 0) ++ err(1, "statfs ./b"); ++ fsid = fs.f_fsid; ++ error = statfs("./root", &fs); ++ if (error != 0) ++ err(1, "statfs ./root"); ++ if (fsid.val[0] != fs.f_fsid.val[0] || ++ fsid.val[1] != fs.f_fsid.val[1]) { ++ error = unmount("./root/b", 0); ++ if (error != 0) ++ err(1, "unmount ./root/b"); ++ } ++ ++ jid = jail_getid("nullfs_jail_root_test"); ++ if (jid >= 0) { ++ error = jail_remove(jid); ++ if (error != 0) ++ err(1, "jail_remove"); ++ } ++} ++ ++ATF_TP_ADD_TCS(tp) ++{ ++ ATF_TP_ADD_TC(tp, jail_root); ++ return (atf_no_error()); ++} diff --git a/website/static/security/patches/SA-26:02/jail-13.patch.asc b/website/static/security/patches/SA-26:02/jail-13.patch.asc new file mode 100644 index 0000000000..a968ffbf0d --- /dev/null +++ b/website/static/security/patches/SA-26:02/jail-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NVgACgkQbljekB8A +Gu8CDw/+JpjJVV0juv2j4rjtk0M4teqTSmKOfbRlHvAZNnmxV7bzfnF3yZZG3y25 +kLt0VPMkvJrZJezqGlgcQeGNoHxHAX7XMOqKCvHgK+8v6wUaHweiQbrKQl5E9byC +eYPWlBvhqa09JJ8JDb1oC5hEW6uGFxqORnIpC2cqSQfZtamL17YVQhMOvHmQc62w +gjPQFJUMuQ7mbRn5ZLI7r9IfRsHuWMysi5FGn8tMHCjppZbqCLOgSpAb7sFQFtkF +7M19GRTZRyr/Lp6W2OEYGUZy34qhwV4mfQfaTfSS+5h3oLZlvWsDH2vXeI/+fvIw +21/KmwJ+jY5e6mPSSp0hxss+pQF0bpkD3azlQtNmYjCglxuOF+euQMwvYIGfVpiM +cICAMx79Z5suVbefq4yM3dq0KWD1Yet3QXswtxYpB7PtH1G9dA0Eqbdb5gfhg/2e +OcLGzwS4/mjHHh0P92blzQtc5MTIY9fj1ncCkBXRMVelfAp5eQFkfpsdDDfXCwO+ +eOXMx13ZdGM7LtepfOeece82mVHJPJxFsTobKRSiw/O6iXw2cVwtRvhoyrqapi7Z +0ih+IAex4P/2fUM6jS6tJ32TFyl9XmkY45Qb/FTHOH+x7O3wUXIOHNIPyjQO4uOP +R4stALBCE0IBGTwpYdZzaDTOiT1ggBFalxIbFVxHATM4d+vjipA= +=hFiD +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:02/jail-14.patch b/website/static/security/patches/SA-26:02/jail-14.patch new file mode 100644 index 0000000000..d2f5b59000 --- /dev/null +++ b/website/static/security/patches/SA-26:02/jail-14.patch @@ -0,0 +1,498 @@ +--- sys/fs/nullfs/null_vnops.c.orig ++++ sys/fs/nullfs/null_vnops.c +@@ -389,7 +389,7 @@ + { + struct componentname *cnp = ap->a_cnp; + struct vnode *dvp = ap->a_dvp; +- int flags = cnp->cn_flags; ++ uint64_t flags = cnp->cn_flags; + struct vnode *vp, *ldvp, *lvp; + struct mount *mp; + int error; +@@ -407,17 +407,25 @@ + + /* + * Renames in the lower mounts might create an inconsistent +- * configuration where lower vnode is moved out of the +- * directory tree remounted by our null mount. Do not try to +- * handle it fancy, just avoid VOP_LOOKUP() with DOTDOT name +- * which cannot be handled by VOP, at least passing over lower +- * root. ++ * configuration where lower vnode is moved out of the directory tree ++ * remounted by our null mount. ++ * ++ * Do not try to handle it fancy, just avoid VOP_LOOKUP() with DOTDOT ++ * name which cannot be handled by the VOP. + */ +- if ((ldvp->v_vflag & VV_ROOT) != 0 && (flags & ISDOTDOT) != 0) { +- KASSERT((dvp->v_vflag & VV_ROOT) == 0, +- ("ldvp %p fl %#x dvp %p fl %#x flags %#x", +- ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, flags)); +- return (ENOENT); ++ if ((flags & ISDOTDOT) != 0) { ++ struct nameidata *ndp; ++ ++ if ((ldvp->v_vflag & VV_ROOT) != 0) { ++ KASSERT((dvp->v_vflag & VV_ROOT) == 0, ++ ("ldvp %p fl %#x dvp %p fl %#x flags %#jx", ++ ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, ++ (uintmax_t)flags)); ++ return (ENOENT); ++ } ++ ndp = vfs_lookup_nameidata(cnp); ++ if (ndp != NULL && vfs_lookup_isroot(ndp, ldvp)) ++ return (ENOENT); + } + + /* +--- sys/fs/unionfs/union_vnops.c.orig ++++ sys/fs/unionfs/union_vnops.c +@@ -78,6 +78,21 @@ + VNASSERT(((vp)->v_op == &unionfs_vnodeops), vp, \ + ("%s: non-unionfs vnode", __func__)) + ++static bool ++unionfs_lookup_isroot(struct componentname *cnp, struct vnode *dvp) ++{ ++ struct nameidata *ndp; ++ ++ if (dvp == NULL) ++ return (false); ++ if ((dvp->v_vflag & VV_ROOT) != 0) ++ return (true); ++ ndp = vfs_lookup_nameidata(cnp); ++ if (ndp == NULL) ++ return (false); ++ return (vfs_lookup_isroot(ndp, dvp)); ++} ++ + static int + unionfs_lookup(struct vop_cachedlookup_args *ap) + { +@@ -128,6 +143,12 @@ + if (LOOKUP != nameiop && udvp == NULLVP) + return (EROFS); + ++ if (unionfs_lookup_isroot(cnp, udvp) || ++ unionfs_lookup_isroot(cnp, ldvp)) { ++ error = ENOENT; ++ goto unionfs_lookup_return; ++ } ++ + if (udvp != NULLVP) { + dtmpvp = udvp; + if (ldvp != NULLVP) +--- sys/kern/vfs_cache.c.orig ++++ sys/kern/vfs_cache.c +@@ -4373,7 +4373,7 @@ + (NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \ + FAILIFEXISTS | FOLLOW | EMPTYPATH | LOCKSHARED | ISRESTARTED | WILLBEDIR | \ + ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK | OPENREAD | \ +- OPENWRITE | WANTIOCTLCAPS) ++ OPENWRITE | WANTIOCTLCAPS | NAMEILOOKUP) + + #define CACHE_FPL_INTERNAL_CN_FLAGS \ + (ISDOTDOT | MAKEENTRY | ISLASTCN) +@@ -5186,30 +5186,19 @@ + cache_fplookup_dotdot(struct cache_fpl *fpl) + { + struct nameidata *ndp; +- struct componentname *cnp; + struct namecache *ncp; + struct vnode *dvp; +- struct prison *pr; + u_char nc_flag; + + ndp = fpl->ndp; +- cnp = fpl->cnp; + dvp = fpl->dvp; + +- MPASS(cache_fpl_isdotdot(cnp)); ++ MPASS(cache_fpl_isdotdot(fpl->cnp)); + + /* + * XXX this is racy the same way regular lookup is + */ +- for (pr = cnp->cn_cred->cr_prison; pr != NULL; +- pr = pr->pr_parent) +- if (dvp == pr->pr_root) +- break; +- +- if (dvp == ndp->ni_rootdir || +- dvp == ndp->ni_topdir || +- dvp == rootvnode || +- pr != NULL) { ++ if (vfs_lookup_isroot(ndp, dvp)) { + fpl->tvp = dvp; + fpl->tvp_seqc = vn_seqc_read_any(dvp); + if (seqc_in_modify(fpl->tvp_seqc)) { +--- sys/kern/vfs_lookup.c.orig ++++ sys/kern/vfs_lookup.c +@@ -612,12 +612,12 @@ + } + #endif + ndp->ni_cnd.cn_cred = td->td_ucred; +- KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n", ++ KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x", + __func__, ndp->ni_resflags)); + KASSERT(cnp->cn_cred && td->td_proc, ("namei: bad cred/proc")); + KASSERT((cnp->cn_flags & NAMEI_INTERNAL_FLAGS) == 0, +- ("namei: unexpected flags: %" PRIx64 "\n", +- cnp->cn_flags & NAMEI_INTERNAL_FLAGS)); ++ ("namei: unexpected flags: %#jx", ++ (uintmax_t)(cnp->cn_flags & NAMEI_INTERNAL_FLAGS))); + if (cnp->cn_flags & NOCACHE) + KASSERT(cnp->cn_nameiop != LOOKUP, + ("%s: NOCACHE passed with LOOKUP", __func__)); +@@ -863,6 +863,30 @@ + return (error); + } + ++struct nameidata * ++vfs_lookup_nameidata(struct componentname *cnp) ++{ ++ if ((cnp->cn_flags & NAMEILOOKUP) == 0) ++ return (NULL); ++ return (__containerof(cnp, struct nameidata, ni_cnd)); ++} ++ ++/* ++ * Would a dotdot lookup relative to dvp cause this lookup to cross a jail or ++ * chroot boundary? ++ */ ++bool ++vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp) ++{ ++ for (struct prison *pr = ndp->ni_cnd.cn_cred->cr_prison; pr != NULL; ++ pr = pr->pr_parent) { ++ if (dvp == pr->pr_root) ++ return (true); ++ } ++ return (dvp == ndp->ni_rootdir || dvp == ndp->ni_topdir || ++ dvp == rootvnode); ++} ++ + /* + * FAILIFEXISTS handling. + * +@@ -1021,7 +1045,6 @@ + char *lastchar; /* location of the last character */ + struct vnode *dp = NULL; /* the directory we are searching */ + struct vnode *tdp; /* saved dp */ +- struct prison *pr; + size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */ + int docache; /* == 0 do not cache last component */ + int wantparent; /* 1 => wantparent or lockparent flag */ +@@ -1207,13 +1230,9 @@ + goto bad; + } + for (;;) { +- for (pr = cnp->cn_cred->cr_prison; pr != NULL; +- pr = pr->pr_parent) +- if (dp == pr->pr_root) +- break; +- bool isroot = dp == ndp->ni_rootdir || +- dp == ndp->ni_topdir || dp == rootvnode || +- pr != NULL; ++ bool isroot; ++ ++ isroot = vfs_lookup_isroot(ndp, dp); + if (__predict_false(isroot && (ndp->ni_lcf & + (NI_LCF_STRICTREL | NI_LCF_STRICTREL_KTR)) != 0)) { + if ((ndp->ni_lcf & NI_LCF_STRICTREL_KTR) != 0) +--- sys/kern/vfs_vnops.c.orig ++++ sys/kern/vfs_vnops.c +@@ -197,11 +197,11 @@ + } + + static uint64_t +-open2nameif(int fmode, u_int vn_open_flags) ++open2nameif(int fmode, u_int vn_open_flags, uint64_t cn_flags) + { + uint64_t res; + +- res = ISOPEN | LOCKLEAF; ++ res = ISOPEN | LOCKLEAF | cn_flags; + if ((fmode & O_RESOLVE_BENEATH) != 0) + res |= RBENEATH; + if ((fmode & O_EMPTY_PATH) != 0) +@@ -210,12 +210,17 @@ + res |= OPENREAD; + if ((fmode & FWRITE) != 0) + res |= OPENWRITE; ++ if ((fmode & O_NOFOLLOW) != 0) ++ res &= ~FOLLOW; + if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) + res |= AUDITVNODE1; ++ else ++ res &= ~AUDITVNODE1; + if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0) + res |= NOCAPCHECK; + if ((vn_open_flags & VN_OPEN_WANTIOCTLCAPS) != 0) + res |= WANTIOCTLCAPS; ++ + return (res); + } + +@@ -247,7 +252,9 @@ + return (EINVAL); + else if ((fmode & (O_CREAT | O_DIRECTORY)) == O_CREAT) { + ndp->ni_cnd.cn_nameiop = CREATE; +- ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); ++ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, ++ ndp->ni_cnd.cn_flags); ++ + /* + * Set NOCACHE to avoid flushing the cache when + * rolling in many files at once. +@@ -256,8 +263,8 @@ + * exist despite NOCACHE. + */ + ndp->ni_cnd.cn_flags |= LOCKPARENT | NOCACHE | NC_KEEPPOSENTRY; +- if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) +- ndp->ni_cnd.cn_flags |= FOLLOW; ++ if ((fmode & O_EXCL) != 0) ++ ndp->ni_cnd.cn_flags &= ~FOLLOW; + if ((vn_open_flags & VN_OPEN_INVFS) == 0) + bwillwrite(); + if ((error = namei(ndp)) != 0) +@@ -325,9 +332,8 @@ + } + } else { + ndp->ni_cnd.cn_nameiop = LOOKUP; +- ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); +- ndp->ni_cnd.cn_flags |= (fmode & O_NOFOLLOW) != 0 ? NOFOLLOW : +- FOLLOW; ++ ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, ++ ndp->ni_cnd.cn_flags); + if ((fmode & FWRITE) == 0) + ndp->ni_cnd.cn_flags |= LOCKSHARED; + if ((error = namei(ndp)) != 0) +--- sys/sys/namei.h.orig ++++ sys/sys/namei.h +@@ -152,6 +152,7 @@ + #define LOCKSHARED 0x0100 /* Shared lock leaf */ + #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ + #define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */ ++#define NAMEILOOKUP 0x200000000ULL /* cnp is embedded in nameidata */ + #define MODMASK 0xf000001ffULL /* mask of operational modifiers */ + + /* +@@ -248,7 +249,7 @@ + NDINIT_PREFILL(_ndp); \ + NDINIT_DBG(_ndp); \ + _ndp->ni_cnd.cn_nameiop = op; \ +- _ndp->ni_cnd.cn_flags = flags; \ ++ _ndp->ni_cnd.cn_flags = (flags) | NAMEILOOKUP; \ + _ndp->ni_segflg = segflg; \ + _ndp->ni_dirp = namep; \ + _ndp->ni_dirfd = dirfd; \ +@@ -264,6 +265,7 @@ + filecaps_free(&_ndp->ni_filecaps); \ + _ndp->ni_resflags = 0; \ + _ndp->ni_startdir = NULL; \ ++ _ndp->ni_cnd.cn_flags &= ~NAMEI_INTERNAL_FLAGS; \ + } while (0) + + #define NDPREINIT(ndp) do { \ +@@ -285,6 +287,8 @@ + + int namei(struct nameidata *ndp); + int vfs_lookup(struct nameidata *ndp); ++bool vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp); ++struct nameidata *vfs_lookup_nameidata(struct componentname *cnp); + int vfs_relookup(struct vnode *dvp, struct vnode **vpp, + struct componentname *cnp, bool refstart); + +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -17,6 +17,7 @@ + ATF_TESTS_C+= kern_copyin + ATF_TESTS_C+= kern_descrip_test + ATF_TESTS_C+= fdgrowtable_test ++ATF_TESTS_C+= jail_lookup_root + ATF_TESTS_C+= kill_zombie + .if ${MK_OPENSSL} != "no" + ATF_TESTS_C+= ktls_test +@@ -69,6 +70,7 @@ + PROGS+= pdeathsig_helper + PROGS+= sendfile_helper + ++LIBADD.jail_lookup_root+= jail util + CFLAGS.sys_getrandom+= -I${SRCTOP}/sys/contrib/zstd/lib + LIBADD.sys_getrandom+= zstd + LIBADD.sys_getrandom+= c +--- /dev/null ++++ tests/sys/kern/jail_lookup_root.c +@@ -0,0 +1,171 @@ ++/*- ++ * SPDX-License-Identifier: BSD-2-Clause ++ * ++ * Copyright (c) 2025 Mark Johnston <markj@FreeBSD.org> ++ */ ++ ++#include <sys/param.h> ++#include <sys/jail.h> ++#include <sys/mount.h> ++#include <sys/stat.h> ++#include <sys/uio.h> ++ ++#include <err.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <jail.h> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include <atf-c.h> ++ ++static void ++build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, ++ size_t len) ++{ ++ int i; ++ ++ if (*iovlen < 0) ++ return; ++ i = *iovlen; ++ *iov = realloc(*iov, sizeof **iov * (i + 2)); ++ if (*iov == NULL) { ++ *iovlen = -1; ++ return; ++ } ++ (*iov)[i].iov_base = strdup(name); ++ (*iov)[i].iov_len = strlen(name) + 1; ++ i++; ++ (*iov)[i].iov_base = val; ++ if (len == (size_t)-1) { ++ if (val != NULL) ++ len = strlen(val) + 1; ++ else ++ len = 0; ++ } ++ (*iov)[i].iov_len = (int)len; ++ *iovlen = ++i; ++} ++ ++static void ++free_iovec(struct iovec **iov, int *iovlen) ++{ ++ int i; ++ ++ for (i = 0; i < *iovlen; i += 2) ++ free((*iov)[i].iov_base); ++ free(*iov); ++} ++ ++static void ++mkdir_checked(const char *dir, mode_t mode) ++{ ++ int error; ++ ++ error = mkdir(dir, mode); ++ ATF_REQUIRE_MSG(error == 0 || errno == EEXIST, ++ "mkdir %s: %s", dir, strerror(errno)); ++} ++ ++static void __unused ++mount_nullfs(const char *dir, const char *target) ++{ ++ struct iovec *iov; ++ char errmsg[1024]; ++ int error, iovlen; ++ ++ iov = NULL; ++ iovlen = 0; ++ ++ build_iovec(&iov, &iovlen, __DECONST(char *, "fstype"), ++ __DECONST(char *, "nullfs"), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "fspath"), ++ __DECONST(char *, target), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "from"), ++ __DECONST(char *, dir), (size_t)-1); ++ build_iovec(&iov, &iovlen, __DECONST(char *, "errmsg"), ++ errmsg, sizeof(errmsg)); ++ ++ errmsg[0] = '\0'; ++ error = nmount(iov, iovlen, 0); ++ ATF_REQUIRE_MSG(error == 0, "nmount: %s", ++ errmsg[0] != '\0' ? errmsg : strerror(errno)); ++ ++ free_iovec(&iov, &iovlen); ++} ++ ++ATF_TC_WITH_CLEANUP(jail_root); ++ATF_TC_HEAD(jail_root, tc) ++{ ++ atf_tc_set_md_var(tc, "require.user", "root"); ++} ++ATF_TC_BODY(jail_root, tc) ++{ ++ int error, fd, jid; ++ ++ mkdir_checked("./root", 0755); ++ mkdir_checked("./root/a", 0755); ++ mkdir_checked("./root/b", 0755); ++ mkdir_checked("./root/a/c", 0755); ++ ++ jid = jail_setv(JAIL_CREATE | JAIL_ATTACH, ++ "name", "nullfs_jail_root_test", ++ "allow.mount", "true", ++ "allow.mount.nullfs", "true", ++ "enforce_statfs", "1", ++ "path", "./root", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid >= 0, "jail_setv: %s", jail_errmsg); ++ ++ mount_nullfs("/a", "/b"); ++ ++ error = chdir("/b/c"); ++ ATF_REQUIRE(error == 0); ++ ++ error = rename("/a/c", "/c"); ++ ATF_REQUIRE(error == 0); ++ ++ /* Descending to the jail root should be ok. */ ++ error = chdir(".."); ++ ATF_REQUIRE(error == 0); ++ ++ /* Going beyond the root will trigger an error. */ ++ error = chdir(".."); ++ ATF_REQUIRE_ERRNO(ENOENT, error != 0); ++ fd = open("..", O_RDONLY | O_DIRECTORY); ++ ATF_REQUIRE_ERRNO(ENOENT, fd < 0); ++} ++ATF_TC_CLEANUP(jail_root, tc) ++{ ++ struct statfs fs; ++ fsid_t fsid; ++ int error, jid; ++ ++ error = statfs("./root/b", &fs); ++ if (error != 0) ++ err(1, "statfs ./b"); ++ fsid = fs.f_fsid; ++ error = statfs("./root", &fs); ++ if (error != 0) ++ err(1, "statfs ./root"); ++ if (fsid.val[0] != fs.f_fsid.val[0] || ++ fsid.val[1] != fs.f_fsid.val[1]) { ++ error = unmount("./root/b", 0); ++ if (error != 0) ++ err(1, "unmount ./root/b"); ++ } ++ ++ jid = jail_getid("nullfs_jail_root_test"); ++ if (jid >= 0) { ++ error = jail_remove(jid); ++ if (error != 0) ++ err(1, "jail_remove"); ++ } ++} ++ ++ATF_TP_ADD_TCS(tp) ++{ ++ ATF_TP_ADD_TC(tp, jail_root); ++ return (atf_no_error()); ++} diff --git a/website/static/security/patches/SA-26:02/jail-14.patch.asc b/website/static/security/patches/SA-26:02/jail-14.patch.asc new file mode 100644 index 0000000000..8097e1daa9 --- /dev/null +++ b/website/static/security/patches/SA-26:02/jail-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAml5NVkACgkQbljekB8A +Gu8V0A//WSveX+D5Il4CNAKQuwaiPEudPSI709NvCkB3KMyQylh2R1Y2bCh/dviI +GgffBznKFGkVPlgEt9jkgDsYbOYRMnCJcGcxHFhKJAYmj1EQv6JyMRUgL1o5NRx1 +40J/7pW2HdfYlUFWXUoM3EW1s8TiG7JeiZQbO58kh00HlactjaNaltteVqeIanxB +iCX1vaGY8Ld/Spzwpp2O2VbegP7aaZVIrdVqeWOi1upCUGKpVmONo/WmIr6gBnVw +iXutQ7PttvaoXH8e/amKizkRfNC3t3cJu56BCjWmXBkf/xwu/kIjLzTWaOqqyGTJ +DZmSij5VMpNWWSYyipQUSV5NepgF/09exmpSWauZtwZvFjbi53bMTPvKzr1Sr0Nf +XdFhP5IozGu5sXDbRbVlRZukLb3B1WqrW79ZF0rB8c/fv94JF+cCGEM8rrHQMaQD +Jfn8B9Tbcl0NLF7dEcuo63z01of9fXG/N/PZnHtRwcHoHFRVSZl+cLVuDcUVhd+T +FJ/0O6HmQ+js59qqDIEDpbgEpX8QBbuWObikVc4yMzRWwKE3NHgRykIpMey/HnQ5 +AyveEies/1zXzYJ/d43LvVgHRmnzAo3XvkrKv+Xvnmak0Msqn43UYLOb+OjajUOG +Pk3rngu7uvcWHKR+53JRlt3YHnHhXMk3TA2MgWqX3Ot4cNJkrak= +=n9LM +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:03/blocklistd.patch b/website/static/security/patches/SA-26:03/blocklistd.patch new file mode 100644 index 0000000000..a411292473 --- /dev/null +++ b/website/static/security/patches/SA-26:03/blocklistd.patch @@ -0,0 +1,173 @@ +--- contrib/blocklist/bin/blacklistd.c.orig ++++ contrib/blocklist/bin/blacklistd.c +@@ -191,7 +191,7 @@ + } + + if (getremoteaddress(bi, &rss, &rsl) == -1) +- return; ++ goto out; + + if (debug || bi->bi_msg[0]) { + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); +@@ -204,12 +204,12 @@ + + if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) { + (*lfun)(LOG_DEBUG, "no rule matched"); +- return; ++ goto out; + } + + + if (state_get(state, &c, &dbi) == -1) +- return; ++ goto out; + + if (debug) { + char b1[128], b2[128]; +@@ -269,6 +269,8 @@ + state_put(state, &c, &dbi); + + out: ++ close(bi->bi_fd); ++ + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d " +--- contrib/blocklist/bin/blocklistd.c.orig ++++ contrib/blocklist/bin/blocklistd.c +@@ -191,7 +191,7 @@ + } + + if (getremoteaddress(bi, &rss, &rsl) == -1) +- return; ++ goto out; + + if (debug || bi->bi_msg[0]) { + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); +@@ -204,12 +204,12 @@ + + if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) { + (*lfun)(LOG_DEBUG, "no rule matched"); +- return; ++ goto out; + } + + + if (state_get(state, &c, &dbi) == -1) +- return; ++ goto out; + + if (debug) { + char b1[128], b2[128]; +@@ -269,6 +269,8 @@ + state_put(state, &c, &dbi); + + out: ++ close(bi->bi_fd); ++ + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d " +--- contrib/blocklist/port/popenve.c.orig ++++ contrib/blocklist/port/popenve.c +@@ -111,11 +111,25 @@ + #endif + } + +- if ((cur = malloc(sizeof(*cur))) != NULL) +- return cur; ++ if ((cur = malloc(sizeof(*cur))) != NULL) { ++ if (**type == 'r') { ++ cur->fp = fdopen(pdes[0], *type); ++#ifdef _REENTRANT ++ cur->fd = pdes[0]; ++#endif ++ } else { ++ cur->fp = fdopen(pdes[1], *type); ++#ifdef _REENTRANT ++ cur->fd = pdes[1]; ++#endif ++ } ++ if (cur->fp != NULL) ++ return cur; ++ } + serrno = errno; + (void)close(pdes[0]); + (void)close(pdes[1]); ++ free(cur); + errno = serrno; + return NULL; + } +@@ -125,16 +139,6 @@ + { + struct pid *old; + +- /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams +- from previous popen() calls that remain open in the +- parent process are closed in the new child process. */ +- for (old = pidlist; old; old = old->next) +-#ifdef _REENTRANT +- (void)close(old->fd); /* don't allow a flush */ +-#else +- (void)close(fileno(old->fp)); /* don't allow a flush */ +-#endif +- + if (type[0] == 'r') { + (void)close(pdes[0]); + if (pdes[1] != STDOUT_FILENO) { +@@ -150,31 +154,30 @@ + (void)close(pdes[0]); + } + } ++ ++ /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams ++ from previous popen() calls that remain open in the ++ parent process are closed in the new child process. */ ++ for (old = pidlist; old; old = old->next) { ++#ifdef _REENTRANT ++ (void)close(old->fd); /* don't allow a flush */ ++#else ++ (void)close(fileno(old->fp)); /* don't allow a flush */ ++#endif ++ } + } + + static void + pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type) + { +- FILE *iop; +- +- /* Parent; assume fdopen can't fail. */ +- if (*type == 'r') { +- iop = fdopen(pdes[0], type); +-#ifdef _REENTRANT +- cur->fd = pdes[0]; +-#endif ++ /* Parent */ ++ if (*type == 'r') + (void)close(pdes[1]); +- } else { +- iop = fdopen(pdes[1], type); +-#ifdef _REENTRANT +- cur->fd = pdes[1]; +-#endif ++ else + (void)close(pdes[0]); +- } + + /* Link into list of file descriptors. */ +- cur->fp = iop; +- cur->pid = pid; ++ cur->pid = pid; + cur->next = pidlist; + pidlist = cur; + } +@@ -200,7 +203,7 @@ + #ifdef _REENTRANT + (void)rwlock_rdlock(&pidlist_lock); + #endif +- switch (pid = vfork()) { ++ switch (pid = fork()) { + case -1: /* Error. */ + serrno = errno; + #ifdef _REENTRANT diff --git a/website/static/security/patches/SA-26:03/blocklistd.patch.asc b/website/static/security/patches/SA-26:03/blocklistd.patch.asc new file mode 100644 index 0000000000..faf670e149 --- /dev/null +++ b/website/static/security/patches/SA-26:03/blocklistd.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmLdZMACgkQbljekB8A +Gu8QYQ//aJxjOxEDunwQsv8aCspVlGm6up5wiUFnh6xF3aXytVbCJDBT4pALRAFD +ZSDD1GloBuZZnFQ9J1936gRYV646XKy0LX2BChWCggeKknT8hnzTa/V90IbXD6Vs +t2qgN2kjLceRXR95nDl4GLPh7eaob2Ha+skPwXoRA/gEM0zhO7F2m5aaNh1EXtjh +PvfuHAM2Q12nQXiM6dBmQaFhdK9JvVVYE8OUjn6ZiRPDaqSMR4rVusy50RpXMn0c +lEaI17FZZ7AQfS4c8SwrCiWcemkJJlGWHjhbIN8tH6PxehE5mMyaCT5lIzOg1cdg +SIbJzx1yRGmdFpY7xL56Jw36LrEjHiV6j3mok61qLq+KLa+02Eb7p24KjUsNX/qI +v6v6dYnKeZ98bJmSR6WzPx8oz7+TyR/MrsxCYyNGKyXBXQ59VJXQ9S9Rpl3MyR74 +KYwtKbokIEQbE6wVTh30AAcCgC/jNaE1MGsf3fwVMW1Gq8N+9z7QmNnhAPyzTyuZ +UVExbGU95dRe+hsdU2Gjtk0o9LzwLIXtynsKUapIeCuHd/QhshxuXx60xxyzG+J9 +KrpuFzbl0+tnhgp78aFkCJoCqSqJp16ZNmc6hpnKacnxnkMDvr1sGSRB27M6TZtZ +HFZij7LwR93nHKRdcyxc6A+hLTO2TLBALvZDGabI5/xHGGrrJKw= +=6vju +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:04/jail-13.patch b/website/static/security/patches/SA-26:04/jail-13.patch new file mode 100644 index 0000000000..d59176e649 --- /dev/null +++ b/website/static/security/patches/SA-26:04/jail-13.patch @@ -0,0 +1,1132 @@ +--- sys/compat/cloudabi/cloudabi_fd.c.orig ++++ sys/compat/cloudabi/cloudabi_fd.c +@@ -389,7 +389,7 @@ + int error, oflags; + + /* Obtain file descriptor properties. */ +- error = fget_cap(td, uap->fd, cap_rights_init(&rights), &fp, ++ error = fget_cap(td, uap->fd, cap_rights_init(&rights), NULL, &fp, + &fcaps); + if (error != 0) + return (error); +--- sys/fs/fdescfs/fdesc_vnops.c.orig ++++ sys/fs/fdescfs/fdesc_vnops.c +@@ -515,7 +515,7 @@ + cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); + } else { + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_SET), NULL, &fp); + } + if (error) { + /* +@@ -652,7 +652,7 @@ + VOP_UNLOCK(vn); + + td = curthread; +- error = fget_cap(td, fd_fd, &cap_no_rights, &fp, NULL); ++ error = fget_cap(td, fd_fd, &cap_no_rights, NULL, &fp, NULL); + if (error != 0) + goto out; + +--- sys/kern/kern_descrip.c.orig ++++ sys/kern/kern_descrip.c +@@ -114,7 +114,8 @@ + static void fdunused(struct filedesc *fdp, int fd); + static void fdused(struct filedesc *fdp, int fd); + static int fget_unlocked_seq(struct filedesc *fdp, int fd, +- cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp); ++ const cap_rights_t *needrightsp, uint8_t *flagsp, ++ struct file **fpp, seqc_t *seqp); + static int getmaxfd(struct thread *td); + static u_long *filecaps_copy_prep(const struct filecaps *src); + static void filecaps_copy_finish(const struct filecaps *src, +@@ -470,6 +471,8 @@ + return (error); + } + ++#define FD_RESOLVE_BENEATH 2 ++ + int + kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) + { +@@ -519,7 +522,9 @@ + fde = fdeget_locked(fdp, fd); + if (fde != NULL) { + td->td_retval[0] = +- (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0; ++ ((fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0) | ++ ((fde->fde_flags & UF_RESOLVE_BENEATH) ? ++ FD_RESOLVE_BENEATH : 0); + error = 0; + } + FILEDESC_SUNLOCK(fdp); +@@ -530,8 +535,13 @@ + FILEDESC_XLOCK(fdp); + fde = fdeget_locked(fdp, fd); + if (fde != NULL) { ++ /* ++ * UF_RESOLVE_BENEATH is sticky and cannot be cleared. ++ */ + fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) | +- (arg & FD_CLOEXEC ? UF_EXCLOSE : 0); ++ ((arg & FD_CLOEXEC) != 0 ? UF_EXCLOSE : 0) | ++ ((arg & FD_RESOLVE_BENEATH) != 0 ? ++ UF_RESOLVE_BENEATH : 0); + error = 0; + } + FILEDESC_XUNLOCK(fdp); +@@ -2158,7 +2168,8 @@ + seqc_write_begin(&fde->fde_seqc); + #endif + fde->fde_file = fp; +- fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0; ++ fde->fde_flags = ((flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0) | ++ ((flags & O_RESOLVE_BENEATH) != 0 ? UF_RESOLVE_BENEATH : 0); + if (fcaps != NULL) + filecaps_move(fcaps, &fde->fde_caps); + else +@@ -2978,7 +2989,7 @@ + } + + int +-fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_cap_locked(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp, struct filecaps *havecapsp) + { + struct filedescent *fde; +@@ -3010,8 +3021,8 @@ + } + + int +-fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp) ++fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp) + { + struct filedesc *fdp = td->td_proc->p_fd; + int error; +@@ -3025,7 +3036,8 @@ + + *fpp = NULL; + for (;;) { +- error = fget_unlocked_seq(fdp, fd, needrightsp, &fp, &seq); ++ error = fget_unlocked_seq(fdp, fd, needrightsp, flagsp, &fp, ++ &seq); + if (error != 0) + return (error); + +@@ -3089,7 +3101,7 @@ + + #ifdef CAPABILITIES + int +-fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, bool *fsearch) ++fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, int *flagsp) + { + const struct filedescent *fde; + const struct fdescenttbl *fdt; +@@ -3099,6 +3111,7 @@ + const cap_rights_t *haverights; + cap_rights_t rights; + seqc_t seq; ++ int flags; + + VFS_SMR_ASSERT_ENTERED(); + +@@ -3117,7 +3130,9 @@ + return (EAGAIN); + if (__predict_false(cap_check_inline_transient(haverights, &rights))) + return (EAGAIN); +- *fsearch = ((fp->f_flag & FSEARCH) != 0); ++ flags = fp->f_flag & FSEARCH; ++ flags |= (fde->fde_flags & UF_RESOLVE_BENEATH) != 0 ? ++ O_RESOLVE_BENEATH : 0; + vp = fp->f_vnode; + if (__predict_false(vp == NULL)) { + return (EAGAIN); +@@ -3151,16 +3166,19 @@ + #endif + } + *vpp = vp; ++ *flagsp = flags; + return (0); + } + #else + int +-fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, bool *fsearch) ++fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, int *flagsp) + { ++ const struct filedescent *fde; + const struct fdescenttbl *fdt; + struct filedesc *fdp; + struct file *fp; + struct vnode *vp; ++ int flags; + + VFS_SMR_ASSERT_ENTERED(); + +@@ -3168,10 +3186,13 @@ + fdt = fdp->fd_files; + if (__predict_false((u_int)fd >= fdt->fdt_nfiles)) + return (EBADF); +- fp = fdt->fdt_ofiles[fd].fde_file; ++ fde = &fdt->fdt_ofiles[fd]; ++ fp = fde->fde_file; + if (__predict_false(fp == NULL)) + return (EAGAIN); +- *fsearch = ((fp->f_flag & FSEARCH) != 0); ++ flags = fp->f_flag & FSEARCH; ++ flags |= (fde->fde_flags & UF_RESOLVE_BENEATH) != 0 ? ++ O_RESOLVE_BENEATH : 0; + vp = fp->f_vnode; + if (__predict_false(vp == NULL || vp->v_type != VDIR)) { + return (EAGAIN); +@@ -3186,6 +3207,7 @@ + return (EAGAIN); + filecaps_fill(&ndp->ni_filecaps); + *vpp = vp; ++ *flagsp = flags; + return (0); + } + #endif +@@ -3199,13 +3221,15 @@ + struct componentname *cnp; + cap_rights_t rights; + int error; ++ uint8_t flags; + + td = curthread; + rights = *ndp->ni_rightsneeded; + cap_rights_set_one(&rights, CAP_LOOKUP); + cnp = &ndp->ni_cnd; + +- error = fget_cap(td, ndp->ni_dirfd, &rights, &fp, &ndp->ni_filecaps); ++ error = fget_cap(td, ndp->ni_dirfd, &rights, &flags, &fp, ++ &ndp->ni_filecaps); + if (__predict_false(error != 0)) + return (error); + if (__predict_false(fp->f_ops == &badfileops)) { +@@ -3223,6 +3247,10 @@ + */ + if ((fp->f_flag & FSEARCH) != 0) + cnp->cn_flags |= NOEXECCHECK; ++ if ((flags & UF_RESOLVE_BENEATH) != 0) { ++ cnp->cn_flags |= RBENEATH; ++ ndp->ni_resflags |= NIRES_BENEATH; ++ } + fdrop(fp, td); + + #ifdef CAPABILITIES +@@ -3256,12 +3284,10 @@ + } + + static int +-fget_unlocked_seq(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp, seqc_t *seqp) ++fget_unlocked_seq(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, seqc_t *seqp) + { +-#ifdef CAPABILITIES + const struct filedescent *fde; +-#endif + const struct fdescenttbl *fdt; + struct file *fp; + #ifdef CAPABILITIES +@@ -3269,6 +3295,7 @@ + cap_rights_t haverights; + int error; + #endif ++ uint8_t flags; + + fdt = fdp->fd_files; + if (__predict_false((u_int)fd >= fdt->fdt_nfiles)) +@@ -3287,10 +3314,13 @@ + fde = &fdt->fdt_ofiles[fd]; + haverights = *cap_rights_fde_inline(fde); + fp = fde->fde_file; ++ flags = fde->fde_flags; + if (!seqc_consistent(fd_seqc(fdt, fd), seq)) + continue; + #else +- fp = fdt->fdt_ofiles[fd].fde_file; ++ fde = &fdt->fdt_ofiles[fd]; ++ flags = fde->fde_flags; ++ fp = fde->fde_file; + #endif + if (fp == NULL) + return (EBADF); +@@ -3323,6 +3353,8 @@ + fdrop(fp, curthread); + } + *fpp = fp; ++ if (flagsp != NULL) ++ *flagsp = flags; + if (seqp != NULL) { + #ifdef CAPABILITIES + *seqp = seq; +@@ -3339,8 +3371,8 @@ + * racing with itself. + */ + int +-fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp) ++fget_unlocked_flags(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp) + { + #ifdef CAPABILITIES + const struct filedescent *fde; +@@ -3351,6 +3383,7 @@ + seqc_t seq; + const cap_rights_t *haverights; + #endif ++ uint8_t flags; + + fdt = fdp->fd_files; + if (__predict_false((u_int)fd >= fdt->fdt_nfiles)) { +@@ -3362,8 +3395,10 @@ + fde = &fdt->fdt_ofiles[fd]; + haverights = cap_rights_fde_inline(fde); + fp = fde->fde_file; ++ flags = fde->fde_flags; + #else + fp = fdt->fdt_ofiles[fd].fde_file; ++ flags = fdt->fdt_ofiles[fd].fde_flags; + #endif + if (__predict_false(fp == NULL)) + goto out_fallback; +@@ -3387,12 +3422,21 @@ + #endif + goto out_fdrop; + *fpp = fp; ++ if (flagsp != NULL) ++ *flagsp = flags; + return (0); + out_fdrop: + fdrop(fp, curthread); + out_fallback: + *fpp = NULL; +- return (fget_unlocked_seq(fdp, fd, needrightsp, fpp, NULL)); ++ return (fget_unlocked_seq(fdp, fd, needrightsp, flagsp, fpp, NULL)); ++} ++ ++int ++fget_unlocked(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, ++ struct file **fpp) ++{ ++ return (fget_unlocked_flags(fdp, fd, needrightsp, NULL, fpp)); + } + + /* +@@ -3406,7 +3450,7 @@ + */ + #ifdef CAPABILITIES + int +-fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp) + { + const struct filedescent *fde; +@@ -3436,7 +3480,7 @@ + } + #else + int +-fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp) + { + struct file *fp; +@@ -3472,7 +3516,7 @@ + */ + static __inline int + _fget(struct thread *td, int fd, struct file **fpp, int flags, +- cap_rights_t *needrightsp) ++ const cap_rights_t *needrightsp) + { + struct filedesc *fdp; + struct file *fp; +@@ -3520,15 +3564,15 @@ + } + + int +-fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp) + { + + return (_fget(td, fd, fpp, 0, rightsp)); + } + + int +-fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, +- struct file **fpp) ++fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, ++ vm_prot_t *maxprotp, struct file **fpp) + { + int error; + #ifndef CAPABILITIES +@@ -3546,7 +3590,7 @@ + fdp = td->td_proc->p_fd; + MPASS(cap_rights_is_set(rightsp, CAP_MMAP)); + for (;;) { +- error = fget_unlocked_seq(fdp, fd, rightsp, &fp, &seq); ++ error = fget_unlocked_seq(fdp, fd, rightsp, NULL, &fp, &seq); + if (__predict_false(error != 0)) + return (error); + if (__predict_false(fp->f_ops == &badfileops)) { +@@ -3571,22 +3615,24 @@ + } + + int +-fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + + return (_fget(td, fd, fpp, FREAD, rightsp)); + } + + int +-fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + + return (_fget(td, fd, fpp, FWRITE, rightsp)); + } + + int +-fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl, +- struct file **fpp) ++fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, ++ int needfcntl, struct file **fpp) + { + struct filedesc *fdp = td->td_proc->p_fd; + #ifndef CAPABILITIES +@@ -3599,7 +3645,7 @@ + *fpp = NULL; + MPASS(cap_rights_is_set(rightsp, CAP_FCNTL)); + for (;;) { +- error = fget_unlocked_seq(fdp, fd, rightsp, &fp, &seq); ++ error = fget_unlocked_seq(fdp, fd, rightsp, NULL, &fp, &seq); + if (error != 0) + return (error); + error = cap_fcntl_check(fdp, fd, needfcntl); +@@ -3624,7 +3670,7 @@ + * XXX: what about the unused flags ? + */ + static __inline int +-_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, ++_fgetvp(struct thread *td, int fd, int flags, const cap_rights_t *needrightsp, + struct vnode **vpp) + { + struct file *fp; +@@ -3646,21 +3692,22 @@ + } + + int +-fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, 0, rightsp, vpp)); + } + + int +-fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, ++fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, + struct filecaps *havecaps, struct vnode **vpp) + { + struct filecaps caps; + struct file *fp; + int error; + +- error = fget_cap(td, fd, needrightsp, &fp, &caps); ++ error = fget_cap(td, fd, needrightsp, NULL, &fp, &caps); + if (error != 0) + return (error); + if (fp->f_ops == &badfileops) { +@@ -3685,14 +3732,16 @@ + } + + int +-fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, FREAD, rightsp, vpp)); + } + + int +-fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, FEXEC, rightsp, vpp)); +@@ -3700,7 +3749,7 @@ + + #ifdef notyet + int +-fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, ++fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp) + { + +--- sys/kern/sys_procdesc.c.orig ++++ sys/kern/sys_procdesc.c +@@ -121,7 +121,7 @@ + * died. + */ + int +-procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp, ++procdesc_find(struct thread *td, int fd, const cap_rights_t *rightsp, + struct proc **p) + { + struct procdesc *pd; +@@ -168,7 +168,8 @@ + * Retrieve the PID associated with a process descriptor. + */ + int +-kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp) ++kern_pdgetpid(struct thread *td, int fd, const cap_rights_t *rightsp, ++ pid_t *pidp) + { + struct file *fp; + int error; +--- sys/kern/uipc_mqueue.c.orig ++++ sys/kern/uipc_mqueue.c +@@ -2160,13 +2160,14 @@ + return (error); + } + +-typedef int (*_fgetf)(struct thread *, int, cap_rights_t *, struct file **); ++typedef int (*_fgetf)(struct thread *, int, const cap_rights_t *, ++ struct file **); + + /* + * Get message queue by giving file slot + */ + static int +-_getmq(struct thread *td, int fd, cap_rights_t *rightsp, _fgetf func, ++_getmq(struct thread *td, int fd, const cap_rights_t *rightsp, _fgetf func, + struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) + { + struct mqfs_node *pn; +--- sys/kern/uipc_sem.c.orig ++++ sys/kern/uipc_sem.c +@@ -123,8 +123,8 @@ + semid_t *semidp, mode_t mode, unsigned int value, + int flags, int compat32); + static void ksem_drop(struct ksem *ks); +-static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, +- struct file **fpp); ++static int ksem_get(struct thread *td, semid_t id, ++ const cap_rights_t *rightsp, struct file **fpp); + static struct ksem *ksem_hold(struct ksem *ks); + static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks); + static struct ksem *ksem_lookup(char *path, Fnv32_t fnv); +@@ -588,7 +588,7 @@ + } + + static int +-ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, ++ksem_get(struct thread *td, semid_t id, const cap_rights_t *rightsp, + struct file **fpp) + { + struct ksem *ks; +--- sys/kern/uipc_syscalls.c.orig ++++ sys/kern/uipc_syscalls.c +@@ -91,13 +91,13 @@ + * A reference on the file entry is held upon returning. + */ + int +-getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, ++getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp, u_int *fflagp, struct filecaps *havecapsp) + { + struct file *fp; + int error; + +- error = fget_cap(td, fd, rightsp, &fp, havecapsp); ++ error = fget_cap(td, fd, rightsp, NULL, &fp, havecapsp); + if (error != 0) + return (error); + if (fp->f_type != DTYPE_SOCKET) { +@@ -727,7 +727,7 @@ + struct uio auio; + struct iovec *iov; + struct socket *so; +- cap_rights_t *rights; ++ const cap_rights_t *rights; + #ifdef KTRACE + struct uio *ktruio = NULL; + #endif +--- sys/kern/uipc_usrreq.c.orig ++++ sys/kern/uipc_usrreq.c +@@ -57,7 +57,6 @@ + * need a proper out-of-band + */ + +-#include <sys/cdefs.h> + #include "opt_ddb.h" + + #include <sys/param.h> +@@ -67,6 +66,7 @@ + #include <sys/fcntl.h> + #include <sys/file.h> + #include <sys/filedesc.h> ++#include <sys/jail.h> + #include <sys/kernel.h> + #include <sys/lock.h> + #include <sys/malloc.h> +@@ -1993,22 +1993,34 @@ + free(fdep[0], M_FILECAPS); + } + ++static bool ++restrict_rights(struct file *fp, struct thread *td) ++{ ++ struct prison *prison1, *prison2; ++ ++ prison1 = fp->f_cred->cr_prison; ++ prison2 = td->td_ucred->cr_prison; ++ return (prison1 != prison2 && prison1->pr_root != prison2->pr_root && ++ prison2 != &prison0); ++} ++ + static int + unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) + { + struct thread *td = curthread; /* XXX */ + struct cmsghdr *cm = mtod(control, struct cmsghdr *); +- int i; + int *fdp; + struct filedesc *fdesc = td->td_proc->p_fd; + struct filedescent **fdep; + void *data; + socklen_t clen = control->m_len, datalen; +- int error, newfds; ++ int error, fdflags, newfds; + u_int newlen; + + UNP_LINK_UNLOCK_ASSERT(); + ++ fdflags = (flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; ++ + error = 0; + if (controlp != NULL) /* controlp == NULL => free control messages */ + *controlp = NULL; +@@ -2059,11 +2071,14 @@ + *controlp = NULL; + goto next; + } +- for (i = 0; i < newfds; i++, fdp++) { +- _finstall(fdesc, fdep[i]->fde_file, *fdp, +- (flags & MSG_CMSG_CLOEXEC) != 0 ? O_CLOEXEC : 0, +- &fdep[i]->fde_caps); +- unp_externalize_fp(fdep[i]->fde_file); ++ for (int i = 0; i < newfds; i++, fdp++) { ++ struct file *fp; ++ ++ fp = fdep[i]->fde_file; ++ _finstall(fdesc, fp, *fdp, fdflags | ++ (restrict_rights(fp, td) ? ++ O_RESOLVE_BENEATH : 0), &fdep[i]->fde_caps); ++ unp_externalize_fp(fp); + } + + /* +--- sys/kern/vfs_acl.c.orig ++++ sys/kern/vfs_acl.c +@@ -433,7 +433,7 @@ + + AUDIT_ARG_FD(uap->filedes); + error = getvnode_path(td, uap->filedes, +- cap_rights_init_one(&rights, CAP_ACL_GET), &fp); ++ cap_rights_init_one(&rights, CAP_ACL_GET), NULL, &fp); + if (error == 0) { + error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); + fdrop(fp, td); +@@ -566,7 +566,7 @@ + + AUDIT_ARG_FD(uap->filedes); + error = getvnode_path(td, uap->filedes, +- cap_rights_init_one(&rights, CAP_ACL_CHECK), &fp); ++ cap_rights_init_one(&rights, CAP_ACL_CHECK), NULL, &fp); + if (error == 0) { + error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); + fdrop(fp, td); +--- sys/kern/vfs_cache.c.orig ++++ sys/kern/vfs_cache.c +@@ -4364,17 +4364,23 @@ + { + struct nameidata *ndp; + struct componentname *cnp; +- int error; +- bool fsearch; ++ int error, flags; + + ndp = fpl->ndp; + cnp = fpl->cnp; + +- error = fgetvp_lookup_smr(ndp->ni_dirfd, ndp, vpp, &fsearch); ++ error = fgetvp_lookup_smr(ndp->ni_dirfd, ndp, vpp, &flags); + if (__predict_false(error != 0)) { + return (cache_fpl_aborted(fpl)); + } +- fpl->fsearch = fsearch; ++ if (__predict_false((flags & O_RESOLVE_BENEATH) != 0)) { ++ _Static_assert((CACHE_FPL_SUPPORTED_CN_FLAGS & RBENEATH) == 0, ++ "RBENEATH supported by fplookup"); ++ cache_fpl_smr_exit(fpl); ++ cache_fpl_aborted(fpl); ++ return (EOPNOTSUPP); ++ } ++ fpl->fsearch = (flags & FSEARCH) != 0; + if ((*vpp)->v_type != VDIR) { + if (!((cnp->cn_flags & EMPTYPATH) != 0 && cnp->cn_pnbuf[0] == '\0')) { + cache_fpl_smr_exit(fpl); +--- sys/kern/vfs_extattr.c.orig ++++ sys/kern/vfs_extattr.c +@@ -241,7 +241,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, uap->fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_SET), NULL, &fp); + if (error) + return (error); + +@@ -408,7 +408,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, uap->fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_GET), NULL, &fp); + if (error) + return (error); + +@@ -543,7 +543,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, uap->fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), NULL, &fp); + if (error) + return (error); + +@@ -689,7 +689,7 @@ + AUDIT_ARG_FD(uap->fd); + AUDIT_ARG_VALUE(uap->attrnamespace); + error = getvnode_path(td, uap->fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_LIST), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_LIST), NULL, &fp); + if (error) + return (error); + +--- sys/kern/vfs_syscalls.c.orig ++++ sys/kern/vfs_syscalls.c +@@ -373,7 +373,7 @@ + int error; + + AUDIT_ARG_FD(fd); +- error = getvnode_path(td, fd, &cap_fstatfs_rights, &fp); ++ error = getvnode_path(td, fd, &cap_fstatfs_rights, NULL, &fp); + if (error != 0) + return (error); + vp = fp->f_vnode; +@@ -887,12 +887,17 @@ + struct mount *mp; + struct file *fp; + int error; ++ uint8_t fdflags; + + AUDIT_ARG_FD(uap->fd); +- error = getvnode_path(td, uap->fd, &cap_fchdir_rights, ++ error = getvnode_path(td, uap->fd, &cap_fchdir_rights, &fdflags, + &fp); + if (error != 0) + return (error); ++ if ((fdflags & UF_RESOLVE_BENEATH) != 0) { ++ fdrop(fp, td); ++ return (ENOTCAPABLE); ++ } + vp = fp->f_vnode; + vrefact(vp); + fdrop(fp, td); +@@ -1243,6 +1248,10 @@ + else + #endif + fcaps = NULL; ++ if ((nd.ni_resflags & NIRES_BENEATH) != 0) ++ flags |= O_RESOLVE_BENEATH; ++ else ++ flags &= ~O_RESOLVE_BENEATH; + error = finstall_refed(td, fp, &indx, flags, fcaps); + /* On success finstall_refed() consumes fcaps. */ + if (error != 0) { +@@ -1933,7 +1942,7 @@ + + fp = NULL; + if (fd != FD_NONE) { +- error = getvnode_path(td, fd, &cap_no_rights, &fp); ++ error = getvnode_path(td, fd, &cap_no_rights, NULL, &fp); + if (error != 0) + return (error); + } +@@ -4315,13 +4324,14 @@ + * semantics. + */ + int +-getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, +- struct file **fpp) ++getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, ++ uint8_t *flagsp, struct file **fpp) + { + struct file *fp; + int error; + +- error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp); ++ error = fget_unlocked_flags(td->td_proc->p_fd, fd, rightsp, flagsp, ++ &fp); + if (error != 0) + return (error); + +@@ -4353,11 +4363,12 @@ + * A reference on the file entry is held upon returning. + */ + int +-getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + int error; + +- error = getvnode_path(td, fd, rightsp, fpp); ++ error = getvnode_path(td, fd, rightsp, NULL, fpp); + + /* + * Filter out O_PATH file descriptors, most getvnode() callers +--- sys/sys/file.h.orig ++++ sys/sys/file.h +@@ -251,14 +251,15 @@ + extern int maxfiles; /* kernel limit on number of open files */ + extern int maxfilesperproc; /* per process limit on number of open files */ + +-int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); +-int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp); ++int fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, + vm_prot_t *maxprotp, struct file **fpp); +-int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); +-int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); +-int fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, + int needfcntl, struct file **fpp); + int _fdrop(struct file *fp, struct thread *td); + int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp); +@@ -281,17 +282,17 @@ + + void finit(struct file *, u_int, short, void *, struct fileops *); + void finit_vnode(struct file *, u_int, void *, struct fileops *); +-int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, ++int fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, + struct filecaps *havecaps, struct vnode **vpp); +-int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, bool *fsearch); ++int fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, int *flagsp); + int fgetvp_lookup(int fd, struct nameidata *ndp, struct vnode **vpp); + + static __inline __result_use_check bool +--- sys/sys/filedesc.h.orig ++++ sys/sys/filedesc.h +@@ -136,6 +136,7 @@ + * Per-process open flags. + */ + #define UF_EXCLOSE 0x01 /* auto-close on exec */ ++#define UF_RESOLVE_BENEATH 0x02 /* lookups must be beneath this dir */ + + #ifdef _KERNEL + +@@ -267,22 +268,26 @@ + struct filedesc_to_leader * + filedesc_to_leader_share(struct filedesc_to_leader *fdtol, + struct filedesc *fdp); +-int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, +- struct file **fpp); +-int getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, ++int getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); ++int getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, ++ uint8_t *flagsp, struct file **fpp); + void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); + +-int fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp); +-int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp); ++int fget_cap_locked(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp, ++ struct filecaps *havecapsp); ++int fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp); + /* Return a referenced file from an unlocked descriptor. */ +-int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++int fget_unlocked(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp); ++int fget_unlocked_flags(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, uint8_t *flagsp, + struct file **fpp); + /* Return a file pointer without a ref. FILEDESC_IS_ONLY_USER must be true. */ +-int fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp); ++int fget_only_user(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp); + #define fput_only_user(fdp, fp) ({ \ + MPASS(FILEDESC_IS_ONLY_USER(fdp)); \ + MPASS(refcount_load(&fp->f_count) > 0); \ +--- sys/sys/namei.h.orig ++++ sys/sys/namei.h +@@ -72,7 +72,7 @@ + */ + const char *ni_dirp; /* pathname pointer */ + enum uio_seg ni_segflg; /* location of pathname */ +- cap_rights_t *ni_rightsneeded; /* rights required to look up vnode */ ++ const cap_rights_t *ni_rightsneeded; /* rights needed to look up vnode */ + /* + * Arguments to lookup. + */ +@@ -208,6 +208,7 @@ + #define NIRES_ABS 0x00000001 /* Path was absolute */ + #define NIRES_STRICTREL 0x00000002 /* Restricted lookup result */ + #define NIRES_EMPTYPATH 0x00000004 /* EMPTYPATH used */ ++#define NIRES_BENEATH 0x00000008 /* O_RESOLVE_BENEATH is to be inherited */ + + /* + * Flags in ni_lcf, valid for the duration of the namei call. +@@ -250,7 +251,7 @@ + #define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp, td) \ + do { \ + struct nameidata *_ndp = (ndp); \ +- cap_rights_t *_rightsp = (rightsp); \ ++ const cap_rights_t *_rightsp = (rightsp); \ + MPASS(_rightsp != NULL); \ + NDINIT_PREFILL(_ndp); \ + NDINIT_DBG(_ndp); \ +--- sys/sys/procdesc.h.orig ++++ sys/sys/procdesc.h +@@ -94,8 +94,10 @@ + * In-kernel interfaces to process descriptors. + */ + int procdesc_exit(struct proc *); +-int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **); +-int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp); ++int procdesc_find(struct thread *, int fd, const cap_rights_t *, ++ struct proc **); ++int kern_pdgetpid(struct thread *, int fd, const cap_rights_t *, ++ pid_t *pidp); + void procdesc_new(struct proc *, int); + void procdesc_finit(struct procdesc *, struct file *); + pid_t procdesc_pid(struct file *); +--- sys/sys/socketvar.h.orig ++++ sys/sys/socketvar.h +@@ -418,7 +418,7 @@ + */ + int getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, + size_t len); +-int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, ++int getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp, u_int *fflagp, struct filecaps *havecaps); + void soabort(struct socket *so); + int soaccept(struct socket *so, struct sockaddr **nam); +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -75,6 +75,7 @@ + LIBADD.sendfile_helper+= pthread + LIBADD.fdgrowtable_test+= util pthread kvm procstat + LIBADD.sigwait+= rt ++LIBADD.unix_passfd_test+= jail + + NETBSD_ATF_TESTS_C+= lockf_test + NETBSD_ATF_TESTS_C+= mqueue_test +--- tests/sys/kern/unix_passfd_test.c.orig ++++ tests/sys/kern/unix_passfd_test.c +@@ -25,15 +25,18 @@ + * SUCH DAMAGE. + */ + +-#include <sys/cdefs.h> +-#include <sys/types.h> ++#include <sys/param.h> ++#include <sys/jail.h> + #include <sys/socket.h> + #include <sys/stat.h> + #include <sys/sysctl.h> + #include <sys/un.h> ++#include <sys/wait.h> + ++#include <err.h> + #include <errno.h> + #include <fcntl.h> ++#include <jail.h> + #include <limits.h> + #include <stdio.h> + #include <stdlib.h> +@@ -713,6 +716,132 @@ + (void)close(putfd); + } + ++ATF_TC_WITH_CLEANUP(cross_jail_dirfd); ++ATF_TC_HEAD(cross_jail_dirfd, tc) ++{ ++ atf_tc_set_md_var(tc, "require.user", "root"); ++} ++ATF_TC_BODY(cross_jail_dirfd, tc) ++{ ++ int error, sock[2], jid1, jid2, status; ++ pid_t pid1, pid2; ++ ++ domainsocketpair(sock); ++ ++ error = mkdir("./a", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./b", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./c", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./a/c", 0755); ++ ATF_REQUIRE(error == 0); ++ ++ jid1 = jail_setv(JAIL_CREATE, ++ "name", "passfd_test_cross_jail_dirfd1", ++ "path", "./a", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid1 >= 0, "jail_setv: %s", jail_errmsg); ++ ++ jid2 = jail_setv(JAIL_CREATE, ++ "name", "passfd_test_cross_jail_dirfd2", ++ "path", "./b", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid2 >= 0, "jail_setv: %s", jail_errmsg); ++ ++ pid1 = fork(); ++ ATF_REQUIRE(pid1 >= 0); ++ if (pid1 == 0) { ++ ssize_t len; ++ int dfd, error; ++ char ch; ++ ++ error = jail_attach(jid1); ++ if (error != 0) ++ err(1, "jail_attach"); ++ ++ dfd = open(".", O_RDONLY | O_DIRECTORY); ++ if (dfd < 0) ++ err(1, "open(\".\") in jail %d", jid1); ++ ++ ch = 0; ++ len = sendfd_payload(sock[0], dfd, &ch, sizeof(ch)); ++ if (len == -1) ++ err(1, "sendmsg"); ++ ++ _exit(0); ++ } ++ ++ pid2 = fork(); ++ ATF_REQUIRE(pid2 >= 0); ++ if (pid2 == 0) { ++ int dfd, dfd2, error, fd; ++ char ch; ++ ++ error = jail_attach(jid2); ++ if (error != 0) ++ err(1, "jail_attach"); ++ ++ /* Get a directory from outside the jail root. */ ++ recvfd_payload(sock[1], &dfd, &ch, sizeof(ch), ++ CMSG_SPACE(sizeof(int)), 0); ++ ++ if ((fcntl(dfd, F_GETFD) & 2) == 0) ++ errx(1, "dfd does not have FD_RESOLVE_BENEATH set"); ++ ++ /* Make sure we can't chdir. */ ++ error = fchdir(dfd); ++ if (error == 0) ++ errx(1, "fchdir succeeded"); ++ if (errno != ENOTCAPABLE) ++ err(1, "fchdir"); ++ ++ /* Make sure a dotdot access fails. */ ++ fd = openat(dfd, "../c", O_RDONLY | O_DIRECTORY); ++ if (fd >= 0) ++ errx(1, "openat(\"../c\") succeeded"); ++ if (errno != ENOTCAPABLE) ++ err(1, "openat"); ++ ++ /* Accesses within the sender's jail root are ok. */ ++ fd = openat(dfd, "c", O_RDONLY | O_DIRECTORY); ++ if (fd < 0) ++ err(1, "openat(\"c\")"); ++ ++ dfd2 = openat(dfd, "", O_EMPTY_PATH | O_RDONLY | O_DIRECTORY); ++ if (dfd2 < 0) ++ err(1, "openat(\"\")"); ++ if ((fcntl(dfd2, F_GETFD) & 2) == 0) ++ errx(1, "dfd2 does not have FD_RESOLVE_BENEATH set"); ++ ++ _exit(0); ++ } ++ ++ error = waitpid(pid1, &status, 0); ++ ATF_REQUIRE(error != -1); ++ ATF_REQUIRE(WIFEXITED(status)); ++ ATF_REQUIRE(WEXITSTATUS(status) == 0); ++ error = waitpid(pid2, &status, 0); ++ ATF_REQUIRE(error != -1); ++ ATF_REQUIRE(WIFEXITED(status)); ++ ATF_REQUIRE(WEXITSTATUS(status) == 0); ++ ++ closesocketpair(sock); ++} ++ATF_TC_CLEANUP(cross_jail_dirfd, tc) ++{ ++ int jid; ++ ++ jid = jail_getid("passfd_test_cross_jail_dirfd1"); ++ if (jid >= 0 && jail_remove(jid) != 0) ++ err(1, "jail_remove"); ++ jid = jail_getid("passfd_test_cross_jail_dirfd2"); ++ if (jid >= 0 && jail_remove(jid) != 0) ++ err(1, "jail_remove"); ++} ++ + ATF_TP_ADD_TCS(tp) + { + +@@ -728,6 +857,7 @@ + ATF_TP_ADD_TC(tp, truncated_rights); + ATF_TP_ADD_TC(tp, copyout_rights_error); + ATF_TP_ADD_TC(tp, empty_rights_message); ++ ATF_TP_ADD_TC(tp, cross_jail_dirfd); + + return (atf_no_error()); + } diff --git a/website/static/security/patches/SA-26:04/jail-13.patch.asc b/website/static/security/patches/SA-26:04/jail-13.patch.asc new file mode 100644 index 0000000000..fd49904b66 --- /dev/null +++ b/website/static/security/patches/SA-26:04/jail-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmd0N0ACgkQbljekB8A +Gu8+TRAAsBfswJ30fVrbbTg5U3DaBQ6dk3mkaGoG90h+2w7wyM23soU0feBc5G+h +/VVKzvde06F0IeRU4QpV2b+ueYo6QEYfVH12X6ZBg8TFOEvRY3J3jXS+Yn3xPso3 +C8ekal+RartuuyztBBZ/XZ750G4+nCWbm+wrhu1p0o3hW2ZCELnBhLEMolKJSJQH +ZuJTdHREC18qLRsgADJrY7/ruY1JUq1lz95cmh954nP4io/bb4uuwAHslWmLiUB8 +pW/E53xzGjB0G/JECtLWQDpVEr2dcLjSPXMUKCKLiV5ciCbsqC17OHKDNcpqarag +NhFQldmF89fkfKH297XjgTCwTVyYu9097754vPNkKJLSYc7dxE3N1RJuKtzGLp/n +IMq3M4CRXnsZ4BVdHVC7V+6s24LzelR95TVb5ViTV7L/sUoyAYObZEThvsOnHvKp +ZXmKNDGz2QLOWEp65nXnxRCwCs5AaiRap74Mqy+b6/Eakfvzcw53za827DovrhOL +0l131sy6Fpk3aqJ775TimeVWoKzkBBRWRyGq2m9pYIowdGeBXrvuOSjlAx40hV6r +BfbenKk9+WtzFhKGX7C/dZm4cT33w8ZfX+WSQgfksTP8tESFCQZQ2F9svmqiiPNw +K484e8YAd/aXmcYuQKfKj2KITg89NXhDTauOEr/n0SWlnRSFHgg= +=DnsX +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:04/jail-14.patch b/website/static/security/patches/SA-26:04/jail-14.patch new file mode 100644 index 0000000000..74d05e79e1 --- /dev/null +++ b/website/static/security/patches/SA-26:04/jail-14.patch @@ -0,0 +1,1173 @@ +--- sys/fs/fdescfs/fdesc_vnops.c.orig ++++ sys/fs/fdescfs/fdesc_vnops.c +@@ -504,7 +504,7 @@ + cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); + } else { + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_SET), NULL, &fp); + } + if (error) { + /* +@@ -641,7 +641,7 @@ + VOP_UNLOCK(vn); + + td = curthread; +- error = fget_cap(td, fd_fd, &cap_no_rights, &fp, NULL); ++ error = fget_cap(td, fd_fd, &cap_no_rights, NULL, &fp, NULL); + if (error != 0) + goto out; + +--- sys/kern/kern_descrip.c.orig ++++ sys/kern/kern_descrip.c +@@ -111,7 +111,8 @@ + static void fdunused(struct filedesc *fdp, int fd); + static void fdused(struct filedesc *fdp, int fd); + static int fget_unlocked_seq(struct thread *td, int fd, +- cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp); ++ const cap_rights_t *needrightsp, uint8_t *flagsp, ++ struct file **fpp, seqc_t *seqp); + static int getmaxfd(struct thread *td); + static u_long *filecaps_copy_prep(const struct filecaps *src); + static void filecaps_copy_finish(const struct filecaps *src, +@@ -479,6 +480,8 @@ + return (error); + } + ++#define FD_RESOLVE_BENEATH 2 ++ + int + kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) + { +@@ -528,7 +531,9 @@ + fde = fdeget_noref(fdp, fd); + if (fde != NULL) { + td->td_retval[0] = +- (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0; ++ ((fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0) | ++ ((fde->fde_flags & UF_RESOLVE_BENEATH) ? ++ FD_RESOLVE_BENEATH : 0); + error = 0; + } + FILEDESC_SUNLOCK(fdp); +@@ -539,8 +544,13 @@ + FILEDESC_XLOCK(fdp); + fde = fdeget_noref(fdp, fd); + if (fde != NULL) { ++ /* ++ * UF_RESOLVE_BENEATH is sticky and cannot be cleared. ++ */ + fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) | +- (arg & FD_CLOEXEC ? UF_EXCLOSE : 0); ++ ((arg & FD_CLOEXEC) != 0 ? UF_EXCLOSE : 0) | ++ ((arg & FD_RESOLVE_BENEATH) != 0 ? ++ UF_RESOLVE_BENEATH : 0); + error = 0; + } + FILEDESC_XUNLOCK(fdp); +@@ -2165,7 +2175,8 @@ + seqc_write_begin(&fde->fde_seqc); + #endif + fde->fde_file = fp; +- fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0; ++ fde->fde_flags = ((flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0) | ++ ((flags & O_RESOLVE_BENEATH) != 0 ? UF_RESOLVE_BENEATH : 0); + if (fcaps != NULL) + filecaps_move(fcaps, &fde->fde_caps); + else +@@ -2879,7 +2890,7 @@ + } + + int +-fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_cap_noref(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp, struct filecaps *havecapsp) + { + struct filedescent *fde; +@@ -2912,8 +2923,8 @@ + + #ifdef CAPABILITIES + int +-fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp) ++fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp) + { + struct filedesc *fdp = td->td_proc->p_fd; + int error; +@@ -2922,7 +2933,8 @@ + + *fpp = NULL; + for (;;) { +- error = fget_unlocked_seq(td, fd, needrightsp, &fp, &seq); ++ error = fget_unlocked_seq(td, fd, needrightsp, flagsp, &fp, ++ &seq); + if (error != 0) + return (error); + +@@ -2952,11 +2964,11 @@ + } + #else + int +-fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp) ++fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp) + { + int error; +- error = fget_unlocked(td, fd, needrightsp, fpp); ++ error = fget_unlocked_flags(td, fd, needrightsp, flagsp, fpp); + if (havecapsp != NULL && error == 0) + filecaps_fill(havecapsp); + +@@ -3039,7 +3051,7 @@ + + #ifdef CAPABILITIES + int +-fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch) ++fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, int *flagsp) + { + const struct filedescent *fde; + const struct fdescenttbl *fdt; +@@ -3049,7 +3061,7 @@ + const cap_rights_t *haverights; + cap_rights_t rights; + seqc_t seq; +- int fd; ++ int fd, flags; + + VFS_SMR_ASSERT_ENTERED(); + +@@ -3069,7 +3081,9 @@ + return (EAGAIN); + if (__predict_false(cap_check_inline_transient(haverights, &rights))) + return (EAGAIN); +- *fsearch = ((fp->f_flag & FSEARCH) != 0); ++ flags = fp->f_flag & FSEARCH; ++ flags |= (fde->fde_flags & UF_RESOLVE_BENEATH) != 0 ? ++ O_RESOLVE_BENEATH : 0; + vp = fp->f_vnode; + if (__predict_false(vp == NULL)) { + return (EAGAIN); +@@ -3103,17 +3117,19 @@ + #endif + } + *vpp = vp; ++ *flagsp = flags; + return (0); + } + #else + int +-fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch) ++fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, int *flagsp) + { ++ const struct filedescent *fde; + const struct fdescenttbl *fdt; + struct filedesc *fdp; + struct file *fp; + struct vnode *vp; +- int fd; ++ int fd, flags; + + VFS_SMR_ASSERT_ENTERED(); + +@@ -3122,10 +3138,13 @@ + fdt = fdp->fd_files; + if (__predict_false((u_int)fd >= fdt->fdt_nfiles)) + return (EBADF); +- fp = fdt->fdt_ofiles[fd].fde_file; ++ fde = &fdt->fdt_ofiles[fd]; ++ fp = fde->fde_file; + if (__predict_false(fp == NULL)) + return (EAGAIN); +- *fsearch = ((fp->f_flag & FSEARCH) != 0); ++ flags = fp->f_flag & FSEARCH; ++ flags |= (fde->fde_flags & UF_RESOLVE_BENEATH) != 0 ? ++ O_RESOLVE_BENEATH : 0; + vp = fp->f_vnode; + if (__predict_false(vp == NULL || vp->v_type != VDIR)) { + return (EAGAIN); +@@ -3140,6 +3159,7 @@ + return (EAGAIN); + filecaps_fill(&ndp->ni_filecaps); + *vpp = vp; ++ *flagsp = flags; + return (0); + } + #endif +@@ -3153,13 +3173,15 @@ + struct componentname *cnp; + cap_rights_t rights; + int error; ++ uint8_t flags; + + td = curthread; + rights = *ndp->ni_rightsneeded; + cap_rights_set_one(&rights, CAP_LOOKUP); + cnp = &ndp->ni_cnd; + +- error = fget_cap(td, ndp->ni_dirfd, &rights, &fp, &ndp->ni_filecaps); ++ error = fget_cap(td, ndp->ni_dirfd, &rights, &flags, &fp, ++ &ndp->ni_filecaps); + if (__predict_false(error != 0)) + return (error); + if (__predict_false(fp->f_ops == &badfileops)) { +@@ -3177,6 +3199,10 @@ + */ + if ((fp->f_flag & FSEARCH) != 0) + cnp->cn_flags |= NOEXECCHECK; ++ if ((flags & UF_RESOLVE_BENEATH) != 0) { ++ cnp->cn_flags |= RBENEATH; ++ ndp->ni_resflags |= NIRES_BENEATH; ++ } + fdrop(fp, td); + + #ifdef CAPABILITIES +@@ -3223,8 +3249,8 @@ + */ + #ifdef CAPABILITIES + static int +-fget_unlocked_seq(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, seqc_t *seqp) ++fget_unlocked_seq(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, seqc_t *seqp) + { + struct filedesc *fdp; + const struct filedescent *fde; +@@ -3233,6 +3259,7 @@ + seqc_t seq; + cap_rights_t haverights; + int error; ++ uint8_t flags; + + fdp = td->td_proc->p_fd; + fdt = fdp->fd_files; +@@ -3244,6 +3271,7 @@ + fde = &fdt->fdt_ofiles[fd]; + haverights = *cap_rights_fde_inline(fde); + fp = fde->fde_file; ++ flags = fde->fde_flags; + if (__predict_false(fp == NULL)) { + if (seqc_consistent(fd_seqc(fdt, fd), seq)) + return (EBADF); +@@ -3272,19 +3300,21 @@ + fdrop(fp, td); + } + *fpp = fp; +- if (seqp != NULL) { ++ if (flagsp != NULL) ++ *flagsp = flags; ++ if (seqp != NULL) + *seqp = seq; +- } + return (0); + } + #else + static int +-fget_unlocked_seq(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, seqc_t *seqp __unused) ++fget_unlocked_seq(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, seqc_t *seqp __unused) + { + struct filedesc *fdp; + const struct fdescenttbl *fdt; + struct file *fp; ++ uint8_t flags; + + fdp = td->td_proc->p_fd; + fdt = fdp->fd_files; +@@ -3293,6 +3323,7 @@ + + for (;;) { + fp = fdt->fdt_ofiles[fd].fde_file; ++ flags = fdt->fdt_ofiles[fd].fde_flags; + if (__predict_false(fp == NULL)) + return (EBADF); + if (__predict_false(!refcount_acquire_if_not_zero(&fp->f_count))) { +@@ -3309,6 +3340,8 @@ + break; + fdrop(fp, td); + } ++ if (flagsp != NULL) ++ *flagsp = flags; + *fpp = fp; + return (0); + } +@@ -3322,8 +3355,8 @@ + * racing with itself. + */ + int +-fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp) ++fget_unlocked_flags(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp) + { + struct filedesc *fdp; + #ifdef CAPABILITIES +@@ -3335,6 +3368,7 @@ + seqc_t seq; + const cap_rights_t *haverights; + #endif ++ uint8_t flags; + + fdp = td->td_proc->p_fd; + fdt = fdp->fd_files; +@@ -3347,8 +3381,10 @@ + fde = &fdt->fdt_ofiles[fd]; + haverights = cap_rights_fde_inline(fde); + fp = fde->fde_file; ++ flags = fde->fde_flags; + #else + fp = fdt->fdt_ofiles[fd].fde_file; ++ flags = fdt->fdt_ofiles[fd].fde_flags; + #endif + if (__predict_false(fp == NULL)) + goto out_fallback; +@@ -3372,12 +3408,21 @@ + #endif + goto out_fdrop; + *fpp = fp; ++ if (flagsp != NULL) ++ *flagsp = flags; + return (0); + out_fdrop: + fdrop(fp, td); + out_fallback: + *fpp = NULL; +- return (fget_unlocked_seq(td, fd, needrightsp, fpp, NULL)); ++ return (fget_unlocked_seq(td, fd, needrightsp, flagsp, fpp, NULL)); ++} ++ ++int ++fget_unlocked(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ struct file **fpp) ++{ ++ return (fget_unlocked_flags(td, fd, needrightsp, NULL, fpp)); + } + + /* +@@ -3391,7 +3436,7 @@ + */ + #ifdef CAPABILITIES + int +-fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp) + { + const struct filedescent *fde; +@@ -3421,7 +3466,7 @@ + } + #else + int +-fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, ++fget_only_user(struct filedesc *fdp, int fd, const cap_rights_t *needrightsp, + struct file **fpp) + { + struct file *fp; +@@ -3457,7 +3502,7 @@ + */ + static __inline int + _fget(struct thread *td, int fd, struct file **fpp, int flags, +- cap_rights_t *needrightsp) ++ const cap_rights_t *needrightsp) + { + struct file *fp; + int error; +@@ -3503,15 +3548,15 @@ + } + + int +-fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp) + { + + return (_fget(td, fd, fpp, 0, rightsp)); + } + + int +-fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, +- struct file **fpp) ++fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, ++ vm_prot_t *maxprotp, struct file **fpp) + { + int error; + #ifndef CAPABILITIES +@@ -3529,7 +3574,7 @@ + fdp = td->td_proc->p_fd; + MPASS(cap_rights_is_set(rightsp, CAP_MMAP)); + for (;;) { +- error = fget_unlocked_seq(td, fd, rightsp, &fp, &seq); ++ error = fget_unlocked_seq(td, fd, rightsp, NULL, &fp, &seq); + if (__predict_false(error != 0)) + return (error); + if (__predict_false(fp->f_ops == &badfileops)) { +@@ -3554,22 +3599,24 @@ + } + + int +-fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + + return (_fget(td, fd, fpp, FREAD, rightsp)); + } + + int +-fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + + return (_fget(td, fd, fpp, FWRITE, rightsp)); + } + + int +-fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl, +- struct file **fpp) ++fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, ++ int needfcntl, struct file **fpp) + { + #ifndef CAPABILITIES + return (fget_unlocked(td, fd, rightsp, fpp)); +@@ -3582,7 +3629,7 @@ + *fpp = NULL; + MPASS(cap_rights_is_set(rightsp, CAP_FCNTL)); + for (;;) { +- error = fget_unlocked_seq(td, fd, rightsp, &fp, &seq); ++ error = fget_unlocked_seq(td, fd, rightsp, NULL, &fp, &seq); + if (error != 0) + return (error); + error = cap_fcntl_check(fdp, fd, needfcntl); +@@ -3607,7 +3654,7 @@ + * XXX: what about the unused flags ? + */ + static __inline int +-_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, ++_fgetvp(struct thread *td, int fd, int flags, const cap_rights_t *needrightsp, + struct vnode **vpp) + { + struct file *fp; +@@ -3629,21 +3676,22 @@ + } + + int +-fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, 0, rightsp, vpp)); + } + + int +-fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, ++fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, + struct filecaps *havecaps, struct vnode **vpp) + { + struct filecaps caps; + struct file *fp; + int error; + +- error = fget_cap(td, fd, needrightsp, &fp, &caps); ++ error = fget_cap(td, fd, needrightsp, NULL, &fp, &caps); + if (error != 0) + return (error); + if (fp->f_ops == &badfileops) { +@@ -3668,14 +3716,16 @@ + } + + int +-fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, FREAD, rightsp, vpp)); + } + + int +-fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) ++fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct vnode **vpp) + { + + return (_fgetvp(td, fd, FEXEC, rightsp, vpp)); +@@ -3683,7 +3733,7 @@ + + #ifdef notyet + int +-fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, ++fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp) + { + +--- sys/kern/sys_procdesc.c.orig ++++ sys/kern/sys_procdesc.c +@@ -121,7 +121,7 @@ + * died. + */ + int +-procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp, ++procdesc_find(struct thread *td, int fd, const cap_rights_t *rightsp, + struct proc **p) + { + struct procdesc *pd; +@@ -168,7 +168,8 @@ + * Retrieve the PID associated with a process descriptor. + */ + int +-kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp) ++kern_pdgetpid(struct thread *td, int fd, const cap_rights_t *rightsp, ++ pid_t *pidp) + { + struct file *fp; + int error; +--- sys/kern/uipc_mqueue.c.orig ++++ sys/kern/uipc_mqueue.c +@@ -2155,13 +2155,14 @@ + return (error); + } + +-typedef int (*_fgetf)(struct thread *, int, cap_rights_t *, struct file **); ++typedef int (*_fgetf)(struct thread *, int, const cap_rights_t *, ++ struct file **); + + /* + * Get message queue by giving file slot + */ + static int +-_getmq(struct thread *td, int fd, cap_rights_t *rightsp, _fgetf func, ++_getmq(struct thread *td, int fd, const cap_rights_t *rightsp, _fgetf func, + struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) + { + struct mqfs_node *pn; +--- sys/kern/uipc_sem.c.orig ++++ sys/kern/uipc_sem.c +@@ -123,8 +123,8 @@ + semid_t *semidp, mode_t mode, unsigned int value, + int flags, int compat32); + static void ksem_drop(struct ksem *ks); +-static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, +- struct file **fpp); ++static int ksem_get(struct thread *td, semid_t id, ++ const cap_rights_t *rightsp, struct file **fpp); + static struct ksem *ksem_hold(struct ksem *ks); + static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks); + static struct ksem *ksem_lookup(char *path, Fnv32_t fnv); +@@ -587,7 +587,7 @@ + } + + static int +-ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, ++ksem_get(struct thread *td, semid_t id, const cap_rights_t *rightsp, + struct file **fpp) + { + struct ksem *ks; +--- sys/kern/uipc_syscalls.c.orig ++++ sys/kern/uipc_syscalls.c +@@ -87,13 +87,13 @@ + * A reference on the file entry is held upon returning. + */ + int +-getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, ++getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp, struct filecaps *havecapsp) + { + struct file *fp; + int error; + +- error = fget_cap(td, fd, rightsp, &fp, havecapsp); ++ error = fget_cap(td, fd, rightsp, NULL, &fp, havecapsp); + if (__predict_false(error != 0)) + return (error); + if (__predict_false(fp->f_type != DTYPE_SOCKET)) { +@@ -107,7 +107,8 @@ + } + + int +-getsock(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++getsock(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + struct file *fp; + int error; +@@ -737,7 +738,7 @@ + struct uio auio; + struct iovec *iov; + struct socket *so; +- cap_rights_t *rights; ++ const cap_rights_t *rights; + #ifdef KTRACE + struct uio *ktruio = NULL; + #endif +--- sys/kern/uipc_usrreq.c.orig ++++ sys/kern/uipc_usrreq.c +@@ -58,7 +58,6 @@ + * need a proper out-of-band + */ + +-#include <sys/cdefs.h> + #include "opt_ddb.h" + + #include <sys/param.h> +@@ -68,6 +67,7 @@ + #include <sys/fcntl.h> + #include <sys/file.h> + #include <sys/filedesc.h> ++#include <sys/jail.h> + #include <sys/kernel.h> + #include <sys/lock.h> + #include <sys/malloc.h> +@@ -2433,22 +2433,34 @@ + free(fdep[0], M_FILECAPS); + } + ++static bool ++restrict_rights(struct file *fp, struct thread *td) ++{ ++ struct prison *prison1, *prison2; ++ ++ prison1 = fp->f_cred->cr_prison; ++ prison2 = td->td_ucred->cr_prison; ++ return (prison1 != prison2 && prison1->pr_root != prison2->pr_root && ++ prison2 != &prison0); ++} ++ + static int + unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) + { + struct thread *td = curthread; /* XXX */ + struct cmsghdr *cm = mtod(control, struct cmsghdr *); +- int i; + int *fdp; + struct filedesc *fdesc = td->td_proc->p_fd; + struct filedescent **fdep; + void *data; + socklen_t clen = control->m_len, datalen; +- int error, newfds; ++ int error, fdflags, newfds; + u_int newlen; + + UNP_LINK_UNLOCK_ASSERT(); + ++ fdflags = (flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; ++ + error = 0; + if (controlp != NULL) /* controlp == NULL => free control messages */ + *controlp = NULL; +@@ -2490,11 +2502,14 @@ + *controlp = NULL; + goto next; + } +- for (i = 0; i < newfds; i++, fdp++) { +- _finstall(fdesc, fdep[i]->fde_file, *fdp, +- (flags & MSG_CMSG_CLOEXEC) != 0 ? O_CLOEXEC : 0, +- &fdep[i]->fde_caps); +- unp_externalize_fp(fdep[i]->fde_file); ++ for (int i = 0; i < newfds; i++, fdp++) { ++ struct file *fp; ++ ++ fp = fdep[i]->fde_file; ++ _finstall(fdesc, fp, *fdp, fdflags | ++ (restrict_rights(fp, td) ? ++ O_RESOLVE_BENEATH : 0), &fdep[i]->fde_caps); ++ unp_externalize_fp(fp); + } + + /* +--- sys/kern/vfs_acl.c.orig ++++ sys/kern/vfs_acl.c +@@ -435,7 +435,7 @@ + + AUDIT_ARG_FD(uap->filedes); + error = getvnode_path(td, uap->filedes, +- cap_rights_init_one(&rights, CAP_ACL_GET), &fp); ++ cap_rights_init_one(&rights, CAP_ACL_GET), NULL, &fp); + if (error == 0) { + error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); + fdrop(fp, td); +@@ -570,7 +570,7 @@ + + AUDIT_ARG_FD(uap->filedes); + error = getvnode_path(td, uap->filedes, +- cap_rights_init_one(&rights, CAP_ACL_CHECK), &fp); ++ cap_rights_init_one(&rights, CAP_ACL_CHECK), NULL, &fp); + if (error == 0) { + error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); + fdrop(fp, td); +--- sys/kern/vfs_cache.c.orig ++++ sys/kern/vfs_cache.c +@@ -4445,17 +4445,23 @@ + { + struct nameidata *ndp; + struct componentname *cnp; +- int error; +- bool fsearch; ++ int error, flags; + + ndp = fpl->ndp; + cnp = fpl->cnp; + +- error = fgetvp_lookup_smr(ndp, vpp, &fsearch); ++ error = fgetvp_lookup_smr(ndp, vpp, &flags); + if (__predict_false(error != 0)) { + return (cache_fpl_aborted(fpl)); + } +- fpl->fsearch = fsearch; ++ if (__predict_false((flags & O_RESOLVE_BENEATH) != 0)) { ++ _Static_assert((CACHE_FPL_SUPPORTED_CN_FLAGS & RBENEATH) == 0, ++ "RBENEATH supported by fplookup"); ++ cache_fpl_smr_exit(fpl); ++ cache_fpl_aborted(fpl); ++ return (EOPNOTSUPP); ++ } ++ fpl->fsearch = (flags & FSEARCH) != 0; + if ((*vpp)->v_type != VDIR) { + if (!((cnp->cn_flags & EMPTYPATH) != 0 && cnp->cn_pnbuf[0] == '\0')) { + cache_fpl_smr_exit(fpl); +--- sys/kern/vfs_extattr.c.orig ++++ sys/kern/vfs_extattr.c +@@ -254,7 +254,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_SET), NULL, &fp); + if (error) + return (error); + +@@ -442,7 +442,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_GET), NULL, &fp); + if (error) + return (error); + +@@ -598,7 +598,7 @@ + AUDIT_ARG_TEXT(attrname); + + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), NULL, &fp); + if (error) + return (error); + +@@ -765,7 +765,7 @@ + AUDIT_ARG_FD(fd); + AUDIT_ARG_VALUE(attrnamespace); + error = getvnode_path(td, fd, +- cap_rights_init_one(&rights, CAP_EXTATTR_LIST), &fp); ++ cap_rights_init_one(&rights, CAP_EXTATTR_LIST), NULL, &fp); + if (error) + return (error); + +--- sys/kern/vfs_syscalls.c.orig ++++ sys/kern/vfs_syscalls.c +@@ -375,7 +375,7 @@ + int error; + + AUDIT_ARG_FD(fd); +- error = getvnode_path(td, fd, &cap_fstatfs_rights, &fp); ++ error = getvnode_path(td, fd, &cap_fstatfs_rights, NULL, &fp); + if (error != 0) + return (error); + vp = fp->f_vnode; +@@ -898,12 +898,17 @@ + struct mount *mp; + struct file *fp; + int error; ++ uint8_t fdflags; + + AUDIT_ARG_FD(uap->fd); +- error = getvnode_path(td, uap->fd, &cap_fchdir_rights, ++ error = getvnode_path(td, uap->fd, &cap_fchdir_rights, &fdflags, + &fp); + if (error != 0) + return (error); ++ if ((fdflags & UF_RESOLVE_BENEATH) != 0) { ++ fdrop(fp, td); ++ return (ENOTCAPABLE); ++ } + vp = fp->f_vnode; + vrefact(vp); + fdrop(fp, td); +@@ -1252,6 +1257,10 @@ + else + #endif + fcaps = NULL; ++ if ((nd.ni_resflags & NIRES_BENEATH) != 0) ++ flags |= O_RESOLVE_BENEATH; ++ else ++ flags &= ~O_RESOLVE_BENEATH; + error = finstall_refed(td, fp, &indx, flags, fcaps); + /* On success finstall_refed() consumes fcaps. */ + if (error != 0) { +@@ -1939,7 +1948,7 @@ + + fp = NULL; + if (fd != FD_NONE) { +- error = getvnode_path(td, fd, &cap_no_rights, &fp); ++ error = getvnode_path(td, fd, &cap_no_rights, NULL, &fp); + if (error != 0) + return (error); + } +@@ -4325,13 +4334,13 @@ + * semantics. + */ + int +-getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, +- struct file **fpp) ++getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, ++ uint8_t *flagsp, struct file **fpp) + { + struct file *fp; + int error; + +- error = fget_unlocked(td, fd, rightsp, &fp); ++ error = fget_unlocked_flags(td, fd, rightsp, flagsp, &fp); + if (error != 0) + return (error); + +@@ -4363,11 +4372,12 @@ + * A reference on the file entry is held upon returning. + */ + int +-getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) ++getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp) + { + int error; + +- error = getvnode_path(td, fd, rightsp, fpp); ++ error = getvnode_path(td, fd, rightsp, NULL, fpp); + if (__predict_false(error != 0)) + return (error); + +--- sys/sys/file.h.orig ++++ sys/sys/file.h +@@ -257,14 +257,15 @@ + extern int maxfiles; /* kernel limit on number of open files */ + extern int maxfilesperproc; /* per process limit on number of open files */ + +-int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); +-int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget(struct thread *td, int fd, const cap_rights_t *rightsp, ++ struct file **fpp); ++int fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, + vm_prot_t *maxprotp, struct file **fpp); +-int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); +-int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); +-int fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, ++int fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, + int needfcntl, struct file **fpp); + int _fdrop(struct file *fp, struct thread *td); + int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp); +@@ -289,17 +290,17 @@ + + void finit(struct file *, u_int, short, void *, const struct fileops *); + void finit_vnode(struct file *, u_int, void *, const struct fileops *); +-int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, ++int fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, + struct filecaps *havecaps, struct vnode **vpp); +-int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, ++int fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, + struct vnode **vpp); +-int fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch); ++int fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, int *flagsp); + int fgetvp_lookup(struct nameidata *ndp, struct vnode **vpp); + + static __inline __result_use_check bool +--- sys/sys/filedesc.h.orig ++++ sys/sys/filedesc.h +@@ -150,6 +150,7 @@ + * Per-process open flags. + */ + #define UF_EXCLOSE 0x01 /* auto-close on exec */ ++#define UF_RESOLVE_BENEATH 0x02 /* lookups must be beneath this dir */ + + #ifdef _KERNEL + +@@ -277,22 +278,26 @@ + struct filedesc_to_leader * + filedesc_to_leader_share(struct filedesc_to_leader *fdtol, + struct filedesc *fdp); +-int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, +- struct file **fpp); +-int getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, ++int getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); ++int getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, ++ uint8_t *flagsp, struct file **fpp); + void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); + +-int fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp); +-int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, +- struct file **fpp, struct filecaps *havecapsp); ++int fget_cap_noref(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp, ++ struct filecaps *havecapsp); ++int fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, ++ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp); + /* Return a referenced file from an unlocked descriptor. */ +-int fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp, ++int fget_unlocked(struct thread *td, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp); ++int fget_unlocked_flags(struct thread *td, int fd, ++ const cap_rights_t *needrightsp, uint8_t *flagsp, + struct file **fpp); + /* Return a file pointer without a ref. FILEDESC_IS_ONLY_USER must be true. */ +-int fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, +- struct file **fpp); ++int fget_only_user(struct filedesc *fdp, int fd, ++ const cap_rights_t *needrightsp, struct file **fpp); + #define fput_only_user(fdp, fp) ({ \ + MPASS(FILEDESC_IS_ONLY_USER(fdp)); \ + MPASS(refcount_load(&fp->f_count) > 0); \ +--- sys/sys/namei.h.orig ++++ sys/sys/namei.h +@@ -70,7 +70,7 @@ + */ + const char *ni_dirp; /* pathname pointer */ + enum uio_seg ni_segflg; /* location of pathname */ +- cap_rights_t *ni_rightsneeded; /* rights required to look up vnode */ ++ const cap_rights_t *ni_rightsneeded; /* rights needed to look up vnode */ + /* + * Arguments to lookup. + */ +@@ -195,6 +195,7 @@ + #define NIRES_ABS 0x00000001 /* Path was absolute */ + #define NIRES_STRICTREL 0x00000002 /* Restricted lookup result */ + #define NIRES_EMPTYPATH 0x00000004 /* EMPTYPATH used */ ++#define NIRES_BENEATH 0x00000008 /* O_RESOLVE_BENEATH is to be inherited */ + + /* + * Flags in ni_lcf, valid for the duration of the namei call. +@@ -244,7 +245,7 @@ + #define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp) \ + do { \ + struct nameidata *_ndp = (ndp); \ +- cap_rights_t *_rightsp = (rightsp); \ ++ const cap_rights_t *_rightsp = (rightsp); \ + MPASS(_rightsp != NULL); \ + NDINIT_PREFILL(_ndp); \ + NDINIT_DBG(_ndp); \ +--- sys/sys/procdesc.h.orig ++++ sys/sys/procdesc.h +@@ -94,8 +94,10 @@ + * In-kernel interfaces to process descriptors. + */ + int procdesc_exit(struct proc *); +-int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **); +-int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp); ++int procdesc_find(struct thread *, int fd, const cap_rights_t *, ++ struct proc **); ++int kern_pdgetpid(struct thread *, int fd, const cap_rights_t *, ++ pid_t *pidp); + void procdesc_new(struct proc *, int); + void procdesc_finit(struct procdesc *, struct file *); + pid_t procdesc_pid(struct file *); +--- sys/sys/socketvar.h.orig ++++ sys/sys/socketvar.h +@@ -490,9 +490,9 @@ + */ + int getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, + size_t len); +-int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, ++int getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp, struct filecaps *havecaps); +-int getsock(struct thread *td, int fd, cap_rights_t *rightsp, ++int getsock(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); + void soabort(struct socket *so); + int soaccept(struct socket *so, struct sockaddr **nam); +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -86,6 +86,8 @@ + LIBADD.fdgrowtable_test+= util pthread kvm procstat + LIBADD.sigwait+= rt + LIBADD.ktrace_test+= sysdecode ++LIBADD.unix_passfd_dgram+= jail ++LIBADD.unix_passfd_stream+= jail + + NETBSD_ATF_TESTS_C+= lockf_test + NETBSD_ATF_TESTS_C+= mqueue_test +--- tests/sys/kern/unix_passfd_test.c.orig ++++ tests/sys/kern/unix_passfd_test.c +@@ -28,15 +28,19 @@ + + #include <sys/cdefs.h> + #include <sys/param.h> ++#include <sys/jail.h> + #include <sys/socket.h> + #include <sys/stat.h> + #include <sys/sysctl.h> + #include <sys/time.h> + #include <sys/resource.h> + #include <sys/un.h> ++#include <sys/wait.h> + ++#include <err.h> + #include <errno.h> + #include <fcntl.h> ++#include <jail.h> + #include <limits.h> + #include <stdio.h> + #include <stdlib.h> +@@ -946,6 +950,132 @@ + (void)close(putfd); + } + ++ATF_TC_WITH_CLEANUP(cross_jail_dirfd); ++ATF_TC_HEAD(cross_jail_dirfd, tc) ++{ ++ atf_tc_set_md_var(tc, "require.user", "root"); ++} ++ATF_TC_BODY(cross_jail_dirfd, tc) ++{ ++ int error, sock[2], jid1, jid2, status; ++ pid_t pid1, pid2; ++ ++ domainsocketpair(sock); ++ ++ error = mkdir("./a", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./b", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./c", 0755); ++ ATF_REQUIRE(error == 0); ++ error = mkdir("./a/c", 0755); ++ ATF_REQUIRE(error == 0); ++ ++ jid1 = jail_setv(JAIL_CREATE, ++ "name", "passfd_test_cross_jail_dirfd1", ++ "path", "./a", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid1 >= 0, "jail_setv: %s", jail_errmsg); ++ ++ jid2 = jail_setv(JAIL_CREATE, ++ "name", "passfd_test_cross_jail_dirfd2", ++ "path", "./b", ++ "persist", NULL, ++ NULL); ++ ATF_REQUIRE_MSG(jid2 >= 0, "jail_setv: %s", jail_errmsg); ++ ++ pid1 = fork(); ++ ATF_REQUIRE(pid1 >= 0); ++ if (pid1 == 0) { ++ ssize_t len; ++ int dfd, error; ++ char ch; ++ ++ error = jail_attach(jid1); ++ if (error != 0) ++ err(1, "jail_attach"); ++ ++ dfd = open(".", O_RDONLY | O_DIRECTORY); ++ if (dfd < 0) ++ err(1, "open(\".\") in jail %d", jid1); ++ ++ ch = 0; ++ len = sendfd_payload(sock[0], dfd, &ch, sizeof(ch)); ++ if (len == -1) ++ err(1, "sendmsg"); ++ ++ _exit(0); ++ } ++ ++ pid2 = fork(); ++ ATF_REQUIRE(pid2 >= 0); ++ if (pid2 == 0) { ++ int dfd, dfd2, error, fd; ++ char ch; ++ ++ error = jail_attach(jid2); ++ if (error != 0) ++ err(1, "jail_attach"); ++ ++ /* Get a directory from outside the jail root. */ ++ recvfd_payload(sock[1], &dfd, &ch, sizeof(ch), ++ CMSG_SPACE(sizeof(int)), 0); ++ ++ if ((fcntl(dfd, F_GETFD) & 2) == 0) ++ errx(1, "dfd does not have FD_RESOLVE_BENEATH set"); ++ ++ /* Make sure we can't chdir. */ ++ error = fchdir(dfd); ++ if (error == 0) ++ errx(1, "fchdir succeeded"); ++ if (errno != ENOTCAPABLE) ++ err(1, "fchdir"); ++ ++ /* Make sure a dotdot access fails. */ ++ fd = openat(dfd, "../c", O_RDONLY | O_DIRECTORY); ++ if (fd >= 0) ++ errx(1, "openat(\"../c\") succeeded"); ++ if (errno != ENOTCAPABLE) ++ err(1, "openat"); ++ ++ /* Accesses within the sender's jail root are ok. */ ++ fd = openat(dfd, "c", O_RDONLY | O_DIRECTORY); ++ if (fd < 0) ++ err(1, "openat(\"c\")"); ++ ++ dfd2 = openat(dfd, "", O_EMPTY_PATH | O_RDONLY | O_DIRECTORY); ++ if (dfd2 < 0) ++ err(1, "openat(\"\")"); ++ if ((fcntl(dfd2, F_GETFD) & 2) == 0) ++ errx(1, "dfd2 does not have FD_RESOLVE_BENEATH set"); ++ ++ _exit(0); ++ } ++ ++ error = waitpid(pid1, &status, 0); ++ ATF_REQUIRE(error != -1); ++ ATF_REQUIRE(WIFEXITED(status)); ++ ATF_REQUIRE(WEXITSTATUS(status) == 0); ++ error = waitpid(pid2, &status, 0); ++ ATF_REQUIRE(error != -1); ++ ATF_REQUIRE(WIFEXITED(status)); ++ ATF_REQUIRE(WEXITSTATUS(status) == 0); ++ ++ closesocketpair(sock); ++} ++ATF_TC_CLEANUP(cross_jail_dirfd, tc) ++{ ++ int jid; ++ ++ jid = jail_getid("passfd_test_cross_jail_dirfd1"); ++ if (jid >= 0 && jail_remove(jid) != 0) ++ err(1, "jail_remove"); ++ jid = jail_getid("passfd_test_cross_jail_dirfd2"); ++ if (jid >= 0 && jail_remove(jid) != 0) ++ err(1, "jail_remove"); ++} ++ + ATF_TP_ADD_TCS(tp) + { + +@@ -964,6 +1094,7 @@ + ATF_TP_ADD_TC(tp, truncated_rights); + ATF_TP_ADD_TC(tp, copyout_rights_error); + ATF_TP_ADD_TC(tp, empty_rights_message); ++ ATF_TP_ADD_TC(tp, cross_jail_dirfd); + + return (atf_no_error()); + } diff --git a/website/static/security/patches/SA-26:04/jail-14.patch.asc b/website/static/security/patches/SA-26:04/jail-14.patch.asc new file mode 100644 index 0000000000..8dd6572a76 --- /dev/null +++ b/website/static/security/patches/SA-26:04/jail-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmd0N4ACgkQbljekB8A +Gu+hpQ/9GEN7r0tSCjrjNrKaChoHhMUun4PaWN+fs5HgNeEs8j8pYIHv70nYPxG2 +VhjWYGomFhka5dkHwTWGsHJJuz0BXP2BXachhTEfKu5cA1/SXpbzsF86KSuW4OUt +oGjMWRtyRyI5zVWY5qTPSn4qj3Y5fE3rro8yTjFGzOceOi+/Rsmx2Nfm0llHXP0N +3XtLtlSUHCS1LW3FoDYzJLUuO9l/C3Fv7i7qJmsFJocAS8e2wbkI9aASrawKfr1m +Hil64sxyz7BPF6tDM/HhFKZW/L4qIg+beOCorU2EW/WAwLsKYkcsNEUUZhncT5b8 +9ZnAVt8KJmANR0IBcT5QfuKwTC7XqVg7t7AXpJ0OakAjpeVPLyqNvckh0JS/ebYU +1HGZAjNdwrW4uuqK8pqBoHTQzjoyqZVW/J831+sUtJStqgSQjXKBxWQdc5fVwVPQ +RvkNzKux+YjQ8TaVgj3MAZCWUyS41rky+9rVSkoUNNibyOmcSd71aAZAugMOmZtS +Fm3cowegVobq3coESYnCfAbwz0/SITqGSclodT1MXCaZpJXjVUsNSaXfWnIagGL1 +H7BzydRf8xw1bS73iKjQ3b65HXWJngEXlxr2DVuH8jtAlz7T2VdnrCSPMEuKk2nV +0v6tnVEJDfv7odBXkFTTwe4+Bm6RcT1hsFHsSRjXmqJEVtGQ2j0= +=jLjT +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:05/route.patch b/website/static/security/patches/SA-26:05/route.patch new file mode 100644 index 0000000000..58fca46942 --- /dev/null +++ b/website/static/security/patches/SA-26:05/route.patch @@ -0,0 +1,13 @@ +--- sys/net/rtsock.c.orig ++++ sys/net/rtsock.c +@@ -1875,8 +1875,8 @@ + #endif + dlen = SA_SIZE(sa); + if (cp != NULL && buflen >= dlen) { +- KASSERT(dlen <= sizeof(ss), +- ("%s: sockaddr size overflow", __func__)); ++ if (sa->sa_len > sizeof(ss)) ++ return (EINVAL); + bzero(&ss, sizeof(ss)); + bcopy(sa, &ss, sa->sa_len); + sa = (struct sockaddr *)&ss; diff --git a/website/static/security/patches/SA-26:05/route.patch.asc b/website/static/security/patches/SA-26:05/route.patch.asc new file mode 100644 index 0000000000..ab3c7da7ff --- /dev/null +++ b/website/static/security/patches/SA-26:05/route.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmmdz7gACgkQbljekB8A +Gu8LBhAAu9vpkKqH+V/BxPmPHxsocmeYUWY/TU8cl4QYKswXWVJCLLrdtP0T5cMg +Mhy1XRxVOpKptv5qy7eU4n00e0xkWDR844lgP1rPRDFzf00zq8S59ZHU1eNv5s1a +0cnrfNeFA3MQWNKf+Yz6roXXhpfaGygiSlCm8ioiNASgmniDvWlvAot3l0MUJwbL +ms1puj6JlsCC4wcJLyV+NyFt8wqOFYqZooH4RqDQOYgJWy7vYFWAtlhNkucGYfuG +K5qc10YKOaAhBJadrFUf7ptbdIUjmeqMxulRt+MeuJIaoanIufdfx9AY2fgCm0tP +IhfjzpXA3Nzq89mXe+/bXb140vmtUQTu0vLrjLnb3ROcCNkUEeDjlH27fl0wu/QR +lAVCONpm+eNBJrdVb82Tp6kBf1kg8l0yCX8XGHNtQ3ld5Pm0/bmpcHcFuQhhHw0M +Fq/+PzTCTX6YGJwFGzV+co3sdVBFfA09evGoZIm/oU0R7uKgUas0IabOe7CIQ7e7 +GY4aMxkspYN8p6rpP/q2lJBKGVQxTqQ/ZBzIiO8JIKXDTAxc9RN2jor+ToDaxzar +E8ekFbNSuHJg0x88CszM6i2DYJ0D0tWbZPlKHLJvszrxQsgvq4m/0uNs3lVLMGCv +7sS761MraMKvB69/aGExIKyA5vrGlKukx7Q3jxoT3ouPc323g38= +=b4I3 +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:06/tcp.patch b/website/static/security/patches/SA-26:06/tcp.patch new file mode 100644 index 0000000000..d7be7a9ac7 --- /dev/null +++ b/website/static/security/patches/SA-26:06/tcp.patch @@ -0,0 +1,11 @@ +--- sys/netinet/tcp_subr.c.orig ++++ sys/netinet/tcp_subr.c +@@ -2216,6 +2216,8 @@ + tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt, + tp->snd_nxt, TH_ACK); + tp->last_ack_sent = tp->rcv_nxt; ++ } else { ++ m_freem(m); + } + } + diff --git a/website/static/security/patches/SA-26:06/tcp.patch.asc b/website/static/security/patches/SA-26:06/tcp.patch.asc new file mode 100644 index 0000000000..939ecee86f --- /dev/null +++ b/website/static/security/patches/SA-26:06/tcp.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkV0ACgkQbljekB8A +Gu9xUg//YDZkTuRSscYc6YtrYfnQWBU3clCebVSu3J5gqLhS1xFgW5pDrallSAMY +0aG2sOPLQdmVjy8fs//AfBqRW/eFPlC0okSVNWSS3Ufv27iZB+didjA+B0//1W3G +oOHIzKCZhG7UsGjx2pDcebI9TOAlYGy3yslkOuRwMHzOyOyAsX+WHPHzxicxbSZ5 +FCWbhnxnRDaNDeJ2wlKnrm0tZQvpfPhYTc8e311v1vJSfeIzukocMcg9ffddEuYr +d+kzcv6HuSwz6n7+ZvUSM+wWNnGXWaDCyjLs+fL2H4VZJ5G6+q7ydEe/VwzZHP2b +E2lVTy4AYRewI9dMbOVcs0as8/ZauYaS8dPEuHsuVJSIqseVHEPuSK9aJ1us/XBv +ExRm1mb2lUKkSMWClSA55wiEfAzpgQi/EKMYaF6UFni8PRDQnhfB1zcJouctLLaw +OAgnDgpoNe9IyMrfL+4SdYWSquniGa3GGb4c7mpWZe2CegF1D3RSkv5hbGjstglm +CgTigeXlpMCBKpoz/fpZdBvIUDoj6PSuyVB5wyTQJkcQW7dkX9ziWb5WHq5s7Wz+ +wOMJQwTiuZLidlsN0BvE2PVj8EY2aa8q9CXpZ4cF9djjMakm+WnaaD69RhV54eFc +026hUX0wm//aHzqE6BaaiAac5AciDiibczZ3ombhEhlrEMqXHlQ= +=m/gK +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:07/nvmf.patch b/website/static/security/patches/SA-26:07/nvmf.patch new file mode 100644 index 0000000000..44eaab112a --- /dev/null +++ b/website/static/security/patches/SA-26:07/nvmf.patch @@ -0,0 +1,12 @@ +--- sys/dev/nvmf/controller/nvmft_controller.c ++++ sys/dev/nvmf/controller/nvmft_controller.c +@@ -227,7 +227,7 @@ + if (ctrlr == NULL) { + mtx_unlock(&np->lock); + printf("NVMFT: Nonexistent controller %u for I/O queue %u from %.*s\n", +- ctrlr->cntlid, qid, (int)sizeof(data->hostnqn), ++ cntlid, qid, (int)sizeof(data->hostnqn), + data->hostnqn); + nvmft_connect_invalid_parameters(qp, cmd, true, + offsetof(struct nvmf_fabric_connect_data, cntlid)); + diff --git a/website/static/security/patches/SA-26:07/nvmf.patch.asc b/website/static/security/patches/SA-26:07/nvmf.patch.asc new file mode 100644 index 0000000000..103fbf5f74 --- /dev/null +++ b/website/static/security/patches/SA-26:07/nvmf.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkV8ACgkQbljekB8A +Gu+Yng/8DOZPbBhwa1imzjIUyXE6l26nF6/yOqK3P1HaQ8h6XNTCDaqmmoRfMhlX +EPrMNyST0eN7XEoD6DdEinQyt69h9QphbF3F85yxIzepm6b2C+vKgRCJ3WCH2tRT +twm3KMmLiNw6n22nIv8cJSRvzfF6pYOnTUeu89SD1pONhb+AaWDYAe31xfHdFymd +1rCr7fLOMlkHuhMkGGrQFdWCtuAeFUXfkGYmuyb523WdIQKzSNWO6FWZ3F7uAXbq +dYXG95+Xd88L1C9G1uDE3jfnv4oB9wbf2I+raNQPbGH23TSyuvEJnLcsXLR+3uL+ +tT3RWfNJz+dOWkj0gqF9xK3DKlJxIzgPopzYG7ILqrfJ0syjwot6huDmDSe2az4K +EyFmnHa1qmfAOC15bzsKZVMsxRFcv1U2s7gtQ+vzIZyfU1hZnaNkuwTOgSfkHgIm +4592ctZbKxGIfH/ezm55HyfexB+2KsuDOm6TWj+EIEDRiPhuxWdPCpop4jN2gUnM +EujBoDaw1Z9NPobT65A6WDR3g33wb9HpYJLkG3+scujeY5eOM7dGeP5mHNLNiubZ +lDDCEZJ9Rt7rG+bVSxXObIJx2+GTHaWC9VPa7TgidlzQDF/+HbK9m8Bl66sewe7B +MuFzLe6c8JrjTyZoCNG9+5K3ScsCQO+YBaT6G+Bb6wwOCtFMorU= +=VSzB +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:08/rpcsec_gss.patch b/website/static/security/patches/SA-26:08/rpcsec_gss.patch new file mode 100644 index 0000000000..82896df793 --- /dev/null +++ b/website/static/security/patches/SA-26:08/rpcsec_gss.patch @@ -0,0 +1,51 @@ +--- lib/librpcsec_gss/svc_rpcsec_gss.c.orig ++++ lib/librpcsec_gss/svc_rpcsec_gss.c +@@ -758,6 +758,14 @@ + + memset(rpchdr, 0, sizeof(rpchdr)); + ++ oa = &msg->rm_call.cb_cred; ++ ++ if (oa->oa_length > sizeof(rpchdr) - 8 * BYTES_PER_XDR_UNIT) { ++ log_debug("auth length %d exceeds maximum", oa->oa_length); ++ client->cl_state = CLIENT_STALE; ++ return (FALSE); ++ } ++ + /* Reconstruct RPC header for signing (from xdr_callmsg). */ + buf = rpchdr; + IXDR_PUT_LONG(buf, msg->rm_xid); +@@ -766,7 +774,6 @@ + IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); + IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); + IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); +- oa = &msg->rm_call.cb_cred; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { +--- sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.orig ++++ sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +@@ -1170,6 +1170,15 @@ + + memset(rpchdr, 0, sizeof(rpchdr)); + ++ oa = &msg->rm_call.cb_cred; ++ ++ if (oa->oa_length > sizeof(rpchdr) - 8 * BYTES_PER_XDR_UNIT) { ++ rpc_gss_log_debug("auth length %d exceeds maximum", ++ oa->oa_length); ++ client->cl_state = CLIENT_STALE; ++ return (FALSE); ++ } ++ + /* Reconstruct RPC header for signing (from xdr_callmsg). */ + buf = rpchdr; + IXDR_PUT_LONG(buf, msg->rm_xid); +@@ -1178,7 +1187,6 @@ + IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); + IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); + IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); +- oa = &msg->rm_call.cb_cred; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { diff --git a/website/static/security/patches/SA-26:08/rpcsec_gss.patch.asc b/website/static/security/patches/SA-26:08/rpcsec_gss.patch.asc new file mode 100644 index 0000000000..b88ebb8529 --- /dev/null +++ b/website/static/security/patches/SA-26:08/rpcsec_gss.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEkWIACgkQbljekB8A +Gu/muQ/+IwXcDjdBY49Xf396/tRJeRNsAiAnCZMOJuUxLfRiZM78Z46LkM6FsHoI +D8BuUJK72nJAX/Cy6vzsr88IZhRZwob/McsN15+37akVZdq2u6mZOHWBiVORBVIS +LTaklgxBjleR2JRYdK8Wz11TLBWIFtDgY+Po/9xWFr4pOF1brWDaIRMJVeP3nf4i +MvAewSBxQGyT9fkWEgU6WXQQpsO7Nahv9R4NG/YnFhElsB2NsgVdYoweOkQxJNPY +1N2mMsKadlnfQvSpgdGhmXSBB6pNpK6XXCbYYU2DvjVxKGjHbVJEyRnSZZo7uZ8A +/ZW7u5SMwW1cPIcqgHfkzLxyIFCTKoH2fuiFoo8Gc7f7gDhCyUJ1xZ7ytFm4bLvV +pwLLOleeg3a5LDouA1PbBxN9Y4P/ud0xaQfmfcQsKGzzETiYyHMPM9GvDVx0cTDE ++jvngAhiHn4pcsKOBHPNkxwfkLovFTNAlOqpm+Wa5A9eUZxFO8KYUnnAsEHGIAue +Lvd35kAPgcF5tt0jhAAJr3BQXtHiTue6QqpP9tKPjyYf3o0M/LZMzEqJk4YlJKz/ +rmlTaaDNQjzx8geV5pPCZcOC5CvjdOILXrv343qozJTRksWp3NuuyLYMBUWcXire +nMbH+q85rGlAah9KHmJhQcpka4vaRRlOkHAkV2IUEN0Qoy1inUg= +=R9iR +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:09/pf-14.patch b/website/static/security/patches/SA-26:09/pf-14.patch new file mode 100644 index 0000000000..477dde061e --- /dev/null +++ b/website/static/security/patches/SA-26:09/pf-14.patch @@ -0,0 +1,212 @@ +--- sbin/pfctl/pfctl.c.orig ++++ sbin/pfctl/pfctl.c +@@ -2043,13 +2043,13 @@ + } + } + +- if (pf->opts & PF_OPT_VERBOSE) { ++ if (pf->opts & PF_OPT_VERBOSE || was_present) { + INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); + print_rule(r, name, + pf->opts & PF_OPT_VERBOSE2, + pf->opts & PF_OPT_NUMERIC); + if (was_present) +- printf(" -- rule was already present"); ++ printf(" -- rule was already present\n"); + } + path[len] = '\0'; + pfctl_clear_pool(&r->rpool); +--- sys/netpfil/pf/pf_ioctl.c.orig ++++ sys/netpfil/pf/pf_ioctl.c +@@ -1264,10 +1264,17 @@ + PF_MD5_UPD(pfr, addr.v.tblname); + break; + case PF_ADDR_ADDRMASK: ++ case PF_ADDR_RANGE: + /* XXX ignore af? */ + PF_MD5_UPD(pfr, addr.v.a.addr.addr32); + PF_MD5_UPD(pfr, addr.v.a.mask.addr32); + break; ++ case PF_ADDR_NOROUTE: ++ case PF_ADDR_URPFFAILED: ++ /* These do not use any address data. */ ++ break; ++ default: ++ panic("Unknown address type %d", pfr->addr.type); + } + + PF_MD5_UPD(pfr, port[0]); +@@ -1276,6 +1283,28 @@ + PF_MD5_UPD(pfr, port_op); + } + ++static void ++pf_hash_pool(MD5_CTX *ctx, struct pf_kpool *pool) ++{ ++ uint16_t x; ++ int y; ++ ++ if (pool->cur) { ++ PF_MD5_UPD(pool, cur->addr); ++ PF_MD5_UPD_STR(pool, cur->ifname); ++ } ++ PF_MD5_UPD(pool, key); ++ PF_MD5_UPD(pool, counter); ++ ++ PF_MD5_UPD(pool, mape.offset); ++ PF_MD5_UPD(pool, mape.psidlen); ++ PF_MD5_UPD_HTONS(pool, mape.psid, x); ++ PF_MD5_UPD_HTONL(pool, tblidx, y); ++ PF_MD5_UPD_HTONS(pool, proxy_port[0], x); ++ PF_MD5_UPD_HTONS(pool, proxy_port[1], x); ++ PF_MD5_UPD(pool, opts); ++} ++ + static void + pf_hash_rule_rolling(MD5_CTX *ctx, struct pf_krule *rule) + { +@@ -1286,37 +1315,84 @@ + pf_hash_rule_addr(ctx, &rule->dst); + for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) + PF_MD5_UPD_STR(rule, label[i]); ++ PF_MD5_UPD_HTONL(rule, ridentifier, y); + PF_MD5_UPD_STR(rule, ifname); ++ PF_MD5_UPD_STR(rule, qname); ++ PF_MD5_UPD_STR(rule, pqname); ++ PF_MD5_UPD_STR(rule, tagname); + PF_MD5_UPD_STR(rule, match_tagname); +- PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ ++ ++ PF_MD5_UPD_STR(rule, overload_tblname); ++ ++ pf_hash_pool(ctx, &rule->rpool); ++ + PF_MD5_UPD_HTONL(rule, os_fingerprint, y); ++ ++ PF_MD5_UPD_HTONL(rule, rtableid, y); ++ for (int i = 0; i < PFTM_MAX; i++) ++ PF_MD5_UPD_HTONL(rule, timeout[i], y); ++ PF_MD5_UPD_HTONL(rule, max_states, y); ++ PF_MD5_UPD_HTONL(rule, max_src_nodes, y); ++ PF_MD5_UPD_HTONL(rule, max_src_states, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn_rate.limit, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn_rate.seconds, y); ++ PF_MD5_UPD_HTONS(rule, qid, x); ++ PF_MD5_UPD_HTONS(rule, pqid, x); ++ PF_MD5_UPD_HTONS(rule, dnpipe, x); ++ PF_MD5_UPD_HTONS(rule, dnrpipe, x); ++ PF_MD5_UPD_HTONL(rule, free_flags, y); + PF_MD5_UPD_HTONL(rule, prob, y); ++ ++ PF_MD5_UPD_HTONS(rule, return_icmp, x); ++ PF_MD5_UPD_HTONS(rule, return_icmp6, x); ++ PF_MD5_UPD_HTONS(rule, max_mss, x); ++ PF_MD5_UPD_HTONS(rule, tag, x); /* dup? */ ++ PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ ++ PF_MD5_UPD_HTONS(rule, scrub_flags, x); ++ ++ PF_MD5_UPD(rule, uid.op); + PF_MD5_UPD_HTONL(rule, uid.uid[0], y); + PF_MD5_UPD_HTONL(rule, uid.uid[1], y); +- PF_MD5_UPD(rule, uid.op); ++ PF_MD5_UPD(rule, gid.op); + PF_MD5_UPD_HTONL(rule, gid.gid[0], y); + PF_MD5_UPD_HTONL(rule, gid.gid[1], y); +- PF_MD5_UPD(rule, gid.op); ++ + PF_MD5_UPD_HTONL(rule, rule_flag, y); ++ PF_MD5_UPD_HTONL(rule, rule_ref, y); + PF_MD5_UPD(rule, action); + PF_MD5_UPD(rule, direction); +- PF_MD5_UPD(rule, af); ++ PF_MD5_UPD(rule, log); ++ PF_MD5_UPD(rule, logif); + PF_MD5_UPD(rule, quick); + PF_MD5_UPD(rule, ifnot); + PF_MD5_UPD(rule, match_tag_not); + PF_MD5_UPD(rule, natpass); ++ + PF_MD5_UPD(rule, keep_state); ++ PF_MD5_UPD(rule, af); + PF_MD5_UPD(rule, proto); +- PF_MD5_UPD(rule, type); +- PF_MD5_UPD(rule, code); ++ PF_MD5_UPD_HTONS(rule, type, x); ++ PF_MD5_UPD_HTONS(rule, code, x); + PF_MD5_UPD(rule, flags); + PF_MD5_UPD(rule, flagset); ++ PF_MD5_UPD(rule, min_ttl); + PF_MD5_UPD(rule, allow_opts); + PF_MD5_UPD(rule, rt); ++ PF_MD5_UPD(rule, return_ttl); + PF_MD5_UPD(rule, tos); +- PF_MD5_UPD(rule, scrub_flags); +- PF_MD5_UPD(rule, min_ttl); + PF_MD5_UPD(rule, set_tos); ++ PF_MD5_UPD(rule, anchor_relative); ++ PF_MD5_UPD(rule, anchor_wildcard); ++ ++ PF_MD5_UPD(rule, flush); ++ PF_MD5_UPD(rule, prio); ++ PF_MD5_UPD(rule, set_prio[0]); ++ PF_MD5_UPD(rule, set_prio[1]); ++ ++ PF_MD5_UPD(rule, divert.addr); ++ PF_MD5_UPD_HTONS(rule, divert.port, x); ++ + if (rule->anchor != NULL) + PF_MD5_UPD_STR(rule, anchor->path); + } +--- tests/sys/netpfil/pf/pass_block.sh.orig ++++ tests/sys/netpfil/pf/pass_block.sh +@@ -255,6 +255,43 @@ + pft_cleanup + } + ++atf_test_case "addr_range" "cleanup" ++addr_range_head() ++{ ++ atf_set descr 'Test rulesets with multiple address ranges' ++ atf_set require.user root ++} ++ ++addr_range_body() ++{ ++ pft_init ++ ++ epair=$(vnet_mkepair) ++ ifconfig ${epair}b 192.0.2.2/24 up ++ ++ vnet_mkjail alcatraz ${epair}a ++ jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up ++ ++ # Sanity check ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++ ++ jexec alcatraz pfctl -e ++ pft_set_rules alcatraz \ ++ "block" \ ++ "pass inet from any to 10.100.100.1 - 10.100.100.20" \ ++ "pass inet from any to 192.0.2.1 - 192.0.2.10" ++ ++jexec alcatraz pfctl -sr -vv ++ ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++jexec alcatraz pfctl -sr -vv ++} ++ ++addr_range_cleanup() ++{ ++ pft_cleanup ++} ++ + atf_init_test_cases() + { + atf_add_test_case "v4" +@@ -262,4 +299,5 @@ + atf_add_test_case "noalias" + atf_add_test_case "nested_inline" + atf_add_test_case "urpf" ++ atf_add_test_case "addr_range" + } diff --git a/website/static/security/patches/SA-26:09/pf-14.patch.asc b/website/static/security/patches/SA-26:09/pf-14.patch.asc new file mode 100644 index 0000000000..0b572eee3e --- /dev/null +++ b/website/static/security/patches/SA-26:09/pf-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEp+wACgkQbljekB8A +Gu/hhhAAh86LN5+Snpm3MlfMChSdRAmsl2dqGgpYlPIoBg5v3CDV1N5L7w4UT62D +G70vLkObvtnA4fVw2X962KVonBuvDuCDn/hj2vG0bJxKrtSTaK28B5LutnEnygfv +z9ZIQNUSsT3E1sDzWWv+C0OFKQ+6enjVt7NfuASq8h0vfVq0oDA71Uab2xhMIfAG +TKdC2+aQSGVO2Odenib55Slqi1F51SB1gw+ANLAg7t9+HxC5pQjJO5l08T9TuOvj +FtqjY2qRno7nAC4tJNakSFGAAyVppaHCRjHiCwRjY2BUnjORDZLjUNuw6IVnYvVm +REoeZg4fnP5vPURw7BpDxXejL+uiO/lFiL0kEXHktn6uUdw54t5dI0ssLGui4S94 +NIIxmn7c0rh+TMAyFGwjOFJODQbyWNmjuWnRaR5IOnys7nO0u58evZhl68dDhjrc +w4Z1aAKSGx0P6VY22/+cnZA2bPwDdcalyCzpy8TIKjYYkXL8Y38F8erPRSl3Sm+C +JA2NrRO6/dZanUHQHTjU0a5OE4mEfKUyPpSsm/QjG2x3ZX9yr96P6jIaVwrHUWnA +9B40ztgAPAPXRMT9p4MOm+e2lpCzwoFP4XJab325i9eB4BIkcjndUTqQJGApU7SH +T/xhFPomYbOv4Scou/41qPnXvrym2Q4XpW/il4JOsqKL7c4ClXk= +=n+h+ +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:09/pf-15.patch b/website/static/security/patches/SA-26:09/pf-15.patch new file mode 100644 index 0000000000..19e6cad8c3 --- /dev/null +++ b/website/static/security/patches/SA-26:09/pf-15.patch @@ -0,0 +1,224 @@ +--- sbin/pfctl/pfctl.c.orig ++++ sbin/pfctl/pfctl.c +@@ -2189,13 +2189,13 @@ + } + } + +- if (pf->opts & PF_OPT_VERBOSE) { ++ if (pf->opts & PF_OPT_VERBOSE || was_present) { + INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); + print_rule(r, name, + pf->opts & PF_OPT_VERBOSE2, + pf->opts & PF_OPT_NUMERIC); + if (was_present) +- printf(" -- rule was already present"); ++ printf(" -- rule was already present\n"); + } + path[len] = '\0'; + pfctl_clear_pool(&r->rdr); +--- sys/netpfil/pf/pf_ioctl.c.orig ++++ sys/netpfil/pf/pf_ioctl.c +@@ -1350,10 +1350,18 @@ + PF_MD5_UPD(pfr, addr.v.tblname); + break; + case PF_ADDR_ADDRMASK: ++ case PF_ADDR_RANGE: + /* XXX ignore af? */ + PF_MD5_UPD(pfr, addr.v.a.addr.addr32); + PF_MD5_UPD(pfr, addr.v.a.mask.addr32); + break; ++ case PF_ADDR_NONE: ++ case PF_ADDR_NOROUTE: ++ case PF_ADDR_URPFFAILED: ++ /* These do not use any address data. */ ++ break; ++ default: ++ panic("Unknown address type %d", pfr->addr.type); + } + + PF_MD5_UPD(pfr, port[0]); +@@ -1362,6 +1370,30 @@ + PF_MD5_UPD(pfr, port_op); + } + ++static void ++pf_hash_pool(MD5_CTX *ctx, struct pf_kpool *pool) ++{ ++ uint16_t x; ++ int y; ++ ++ if (pool->cur) { ++ PF_MD5_UPD(pool, cur->addr); ++ PF_MD5_UPD_STR(pool, cur->ifname); ++ PF_MD5_UPD(pool, cur->af); ++ } ++ PF_MD5_UPD(pool, key); ++ PF_MD5_UPD(pool, counter); ++ ++ PF_MD5_UPD(pool, mape.offset); ++ PF_MD5_UPD(pool, mape.psidlen); ++ PF_MD5_UPD_HTONS(pool, mape.psid, x); ++ PF_MD5_UPD_HTONL(pool, tblidx, y); ++ PF_MD5_UPD_HTONS(pool, proxy_port[0], x); ++ PF_MD5_UPD_HTONS(pool, proxy_port[1], x); ++ PF_MD5_UPD(pool, opts); ++ PF_MD5_UPD(pool, ipv6_nexthop_af); ++} ++ + static void + pf_hash_rule_rolling(MD5_CTX *ctx, struct pf_krule *rule) + { +@@ -1372,39 +1404,92 @@ + pf_hash_rule_addr(ctx, &rule->dst); + for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) + PF_MD5_UPD_STR(rule, label[i]); ++ PF_MD5_UPD_HTONL(rule, ridentifier, y); + PF_MD5_UPD_STR(rule, ifname); + PF_MD5_UPD_STR(rule, rcv_ifname); ++ PF_MD5_UPD_STR(rule, qname); ++ PF_MD5_UPD_STR(rule, pqname); ++ PF_MD5_UPD_STR(rule, tagname); + PF_MD5_UPD_STR(rule, match_tagname); +- PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ ++ ++ PF_MD5_UPD_STR(rule, overload_tblname); ++ ++ pf_hash_pool(ctx, &rule->nat); ++ pf_hash_pool(ctx, &rule->rdr); ++ pf_hash_pool(ctx, &rule->route); ++ PF_MD5_UPD_HTONL(rule, pktrate.limit, y); ++ PF_MD5_UPD_HTONL(rule, pktrate.seconds, y); ++ + PF_MD5_UPD_HTONL(rule, os_fingerprint, y); ++ ++ PF_MD5_UPD_HTONL(rule, rtableid, y); ++ for (int i = 0; i < PFTM_MAX; i++) ++ PF_MD5_UPD_HTONL(rule, timeout[i], y); ++ PF_MD5_UPD_HTONL(rule, max_states, y); ++ PF_MD5_UPD_HTONL(rule, max_src_nodes, y); ++ PF_MD5_UPD_HTONL(rule, max_src_states, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn_rate.limit, y); ++ PF_MD5_UPD_HTONL(rule, max_src_conn_rate.seconds, y); ++ PF_MD5_UPD_HTONS(rule, max_pkt_size, y); ++ PF_MD5_UPD_HTONS(rule, qid, x); ++ PF_MD5_UPD_HTONS(rule, pqid, x); ++ PF_MD5_UPD_HTONS(rule, dnpipe, x); ++ PF_MD5_UPD_HTONS(rule, dnrpipe, x); ++ PF_MD5_UPD_HTONL(rule, free_flags, y); + PF_MD5_UPD_HTONL(rule, prob, y); ++ ++ PF_MD5_UPD_HTONS(rule, return_icmp, x); ++ PF_MD5_UPD_HTONS(rule, return_icmp6, x); ++ PF_MD5_UPD_HTONS(rule, max_mss, x); ++ PF_MD5_UPD_HTONS(rule, tag, x); /* dup? */ ++ PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ ++ PF_MD5_UPD_HTONS(rule, scrub_flags, x); ++ ++ PF_MD5_UPD(rule, uid.op); + PF_MD5_UPD_HTONL(rule, uid.uid[0], y); + PF_MD5_UPD_HTONL(rule, uid.uid[1], y); +- PF_MD5_UPD(rule, uid.op); ++ PF_MD5_UPD(rule, gid.op); + PF_MD5_UPD_HTONL(rule, gid.gid[0], y); + PF_MD5_UPD_HTONL(rule, gid.gid[1], y); +- PF_MD5_UPD(rule, gid.op); ++ + PF_MD5_UPD_HTONL(rule, rule_flag, y); ++ PF_MD5_UPD_HTONL(rule, rule_ref, y); + PF_MD5_UPD(rule, action); + PF_MD5_UPD(rule, direction); +- PF_MD5_UPD(rule, af); ++ PF_MD5_UPD(rule, log); ++ PF_MD5_UPD(rule, logif); + PF_MD5_UPD(rule, quick); + PF_MD5_UPD(rule, ifnot); +- PF_MD5_UPD(rule, rcvifnot); + PF_MD5_UPD(rule, match_tag_not); + PF_MD5_UPD(rule, natpass); ++ + PF_MD5_UPD(rule, keep_state); ++ PF_MD5_UPD(rule, af); + PF_MD5_UPD(rule, proto); +- PF_MD5_UPD(rule, type); +- PF_MD5_UPD(rule, code); ++ PF_MD5_UPD_HTONS(rule, type, x); ++ PF_MD5_UPD_HTONS(rule, code, x); + PF_MD5_UPD(rule, flags); + PF_MD5_UPD(rule, flagset); ++ PF_MD5_UPD(rule, min_ttl); + PF_MD5_UPD(rule, allow_opts); + PF_MD5_UPD(rule, rt); ++ PF_MD5_UPD(rule, return_ttl); + PF_MD5_UPD(rule, tos); +- PF_MD5_UPD(rule, scrub_flags); +- PF_MD5_UPD(rule, min_ttl); + PF_MD5_UPD(rule, set_tos); ++ PF_MD5_UPD(rule, anchor_relative); ++ PF_MD5_UPD(rule, anchor_wildcard); ++ ++ PF_MD5_UPD(rule, flush); ++ PF_MD5_UPD(rule, prio); ++ PF_MD5_UPD(rule, set_prio[0]); ++ PF_MD5_UPD(rule, set_prio[1]); ++ PF_MD5_UPD(rule, naf); ++ PF_MD5_UPD(rule, rcvifnot); ++ ++ PF_MD5_UPD(rule, divert.addr); ++ PF_MD5_UPD_HTONS(rule, divert.port, x); ++ + if (rule->anchor != NULL) + PF_MD5_UPD_STR(rule, anchor->path); + } +--- tests/sys/netpfil/pf/pass_block.sh.orig ++++ tests/sys/netpfil/pf/pass_block.sh +@@ -451,6 +451,43 @@ + pft_cleanup + } + ++atf_test_case "addr_range" "cleanup" ++addr_range_head() ++{ ++ atf_set descr 'Test rulesets with multiple address ranges' ++ atf_set require.user root ++} ++ ++addr_range_body() ++{ ++ pft_init ++ ++ epair=$(vnet_mkepair) ++ ifconfig ${epair}b 192.0.2.2/24 up ++ ++ vnet_mkjail alcatraz ${epair}a ++ jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up ++ ++ # Sanity check ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++ ++ jexec alcatraz pfctl -e ++ pft_set_rules alcatraz \ ++ "block" \ ++ "pass inet from any to 10.100.100.1 - 10.100.100.20" \ ++ "pass inet from any to 192.0.2.1 - 192.0.2.10" ++ ++jexec alcatraz pfctl -sr -vv ++ ++ atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 ++jexec alcatraz pfctl -sr -vv ++} ++ ++addr_range_cleanup() ++{ ++ pft_cleanup ++} ++ + atf_init_test_cases() + { + atf_add_test_case "enable_disable" +@@ -462,4 +499,5 @@ + atf_add_test_case "received_on" + atf_add_test_case "optimize_any" + atf_add_test_case "any_if" ++ atf_add_test_case "addr_range" + } diff --git a/website/static/security/patches/SA-26:09/pf-15.patch.asc b/website/static/security/patches/SA-26:09/pf-15.patch.asc new file mode 100644 index 0000000000..fa27926ab0 --- /dev/null +++ b/website/static/security/patches/SA-26:09/pf-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnEp+0ACgkQbljekB8A +Gu8w8Q/+JVp4ZMcd9vM8l+zqCqj2XTUg2887KBnJ+qZRYZvXtNzJpxJTxaEUYe7p +Dj/OsFTxm821shqYxJv5I7lgJpqNNggKn41j/BaOTf3GK6Or8bVKUI3GmCKjEMD/ +AnxILH1WeM0hsFqs2GhtXww1EeFRuKTqNyLbjJ/sEdXI+AQQhYQi4PiFvLXecezh +dpP4FRCU52hqYYz3C4wbW92hZfkVCTHOZEkFbpNYerzxsgLxDOzMLq+FTgPNRUBw +YaNs5rPWbiYqpATsryGKDjT1SS3Y1zyVGcuTMtcvpOK9//il9paexzwLt+6FjUsa +sAGrA+vKfmdFxJBsiHm7IxjMZvkPtvY8TSNnnljLnRtWXdmptucHg11KSX5gzxvw +YsPmu7TwZ3JLzfAZ0jhOn3jRVBqpyZmarBw2txkwVL3WQ7OETwV32HOMLdwwzhXg +nI0aSgWWf3OiPMHLjCogrGE8mnS5yuymfRefMHvMarawMoDOFJQB8bXhe0VwxOke +XypsrHMif5my2+QTi/cQNcJT6dm2qaD9l7xIqJnazV/JID108ff+iQkC2AI349io +ZJ9StSd4owudffN633Aqx6M+ttex5uYb8QzxhqEtgJbDTshU/RCg2pnni3D8r1GC +gf45MYEAllePewusKKoYQDoRF3csF9V43GPHx0LUhgvw4QxMR28= +=QAdP +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:10/tty-13.patch b/website/static/security/patches/SA-26:10/tty-13.patch new file mode 100644 index 0000000000..cbc62f2962 --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-13.patch @@ -0,0 +1,108 @@ +--- sys/kern/tty.c.orig ++++ sys/kern/tty.c +@@ -1262,6 +1262,10 @@ + session->s_ttydp = NULL; + SESS_UNLOCK(session); + ++ if (tp->t_session == session) { ++ tp->t_session = NULL; ++ tp->t_pgrp = NULL; ++ } + tp->t_sessioncnt--; + p->p_flag &= ~P_CONTROLT; + PROC_UNLOCK(p); +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -35,6 +35,7 @@ + PLAIN_TESTS_C+= subr_unit_test + ATF_TESTS_C+= sysctl_kern_proc + ATF_TESTS_C+= sys_getrandom ++PLAIN_TESTS_C+= tiocnotty + ATF_TESTS_C+= tty_pts + ATF_TESTS_C+= unix_passfd_test + ATF_TESTS_C+= unix_seqpacket_test +--- /dev/null ++++ tests/sys/kern/tiocnotty.c +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org> ++ * ++ * SPDX-License-Identifier: BSD-2-Clause ++ */ ++ ++/* ++ * A regression test that exercises a bug where TIOCNOTTY would leave some ++ * dangling pointers behind in the controlling terminal structure. ++ */ ++ ++#include <sys/ioctl.h> ++#include <sys/wait.h> ++ ++#include <err.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++int ++main(void) ++{ ++ int master, slave, status; ++ pid_t child; ++ ++ master = posix_openpt(O_RDWR | O_NOCTTY); ++ if (master < 0) ++ err(1, "posix_openpt"); ++ if (grantpt(master) < 0) ++ err(1, "grantpt"); ++ if (unlockpt(master) < 0) ++ err(1, "unlockpt"); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(3, "ioctl(TIOCSCTTY)"); ++ /* Detach ourselves from the controlling terminal. */ ++ if (ioctl(slave, TIOCNOTTY, 0) < 0) ++ err(4, "ioctl(TIOCNOTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ struct winsize winsz; ++ ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ /* Dereferences dangling t_pgrp pointer in the terminal. */ ++ memset(&winsz, 0xff, sizeof(winsz)); ++ if (ioctl(slave, TIOCSWINSZ, &winsz) < 0) ++ err(3, "ioctl(TIOCSWINSZ)"); ++ /* Dereferences dangling t_session pointer in the terminal. */ ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(4, "ioctl(TIOCSCTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++} diff --git a/website/static/security/patches/SA-26:10/tty-13.patch.asc b/website/static/security/patches/SA-26:10/tty-13.patch.asc new file mode 100644 index 0000000000..fcbdf0dc3b --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaUACgkQbljekB8A +Gu8CGBAArN7j/5++Cn80jErvso5xKBsMuNlWVdKOrxedO8upL+ma03tKqeb3z4Be +kjkO1LuOFFNH3HBjAd5VG9d+hOaXqt1Lcf3AtnJvWru/Xai1m4eEJZYtAaeGlsDq +uozDyMr4D71bzdmNT+yezPiDEo+w8p9niXKf3f1ZWWpEklTgeeKWVFNb4QwSboQg +IYgi9/iH7sSjrzIZoFnC5ZhSdLwMB6RLds8K0XrbLC9DoDmQWw6vJBYEa1Nd9a/X +gv0jgjWetHm6jkDUDq2mtTmWuKlF9+a82KvLxNreen04FduZazxezzfeuriAJAKX +CHE3EREa99uSnarna0xklRIRqzOWLs+ys/7AEBXbzMbRiVtBD8r+Wfy/wiy1sDUZ +TCFea3XwZiI65ys0OL0yiLVqrN5PeDgHjMEqMIQXOejtGoKtsOchjcfpwSVVh26v +YmVEGTJUwJIi9+eN0BQF6nvynl75kK3SH4PUjatm1kX6OjobPMpxtHM9jsZm6qoY +fj8FTh2DcGXglJAzf60YFk6Awx1iYW1RAaIURFvbA9ZzG+K0dN93b1OcWNHgnyAw +WTwl8RTGU0ztvdCwqyyc0yl3g2tDKi4eufJ6QmanP1BjwGig/SufkBE1Qr2hTyLp +rOwNjXPKkSg23W/W4zRn1kyUGLM1ahh/wyPfppy6hxRQb442cWM= +=Fhm4 +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:10/tty-14.3.patch b/website/static/security/patches/SA-26:10/tty-14.3.patch new file mode 100644 index 0000000000..49764c0e05 --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-14.3.patch @@ -0,0 +1,108 @@ +--- sys/kern/tty.c.orig ++++ sys/kern/tty.c +@@ -1262,6 +1262,10 @@ + session->s_ttydp = NULL; + SESS_UNLOCK(session); + ++ if (tp->t_session == session) { ++ tp->t_session = NULL; ++ tp->t_pgrp = NULL; ++ } + tp->t_sessioncnt--; + p->p_flag &= ~P_CONTROLT; + PROC_UNLOCK(p); +--- tests/sys/kern/Makefile.orig ++++ tests/sys/kern/Makefile +@@ -41,6 +41,7 @@ + PLAIN_TESTS_C+= subr_unit_test + ATF_TESTS_C+= sysctl_kern_proc + ATF_TESTS_C+= sys_getrandom ++PLAIN_TESTS_C+= tiocnotty + ATF_TESTS_C+= tty_pts + ATF_TESTS_C+= unix_dgram + ATF_TESTS_C+= unix_passfd_dgram +--- /dev/null ++++ tests/sys/kern/tiocnotty.c +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org> ++ * ++ * SPDX-License-Identifier: BSD-2-Clause ++ */ ++ ++/* ++ * A regression test that exercises a bug where TIOCNOTTY would leave some ++ * dangling pointers behind in the controlling terminal structure. ++ */ ++ ++#include <sys/ioctl.h> ++#include <sys/wait.h> ++ ++#include <err.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++int ++main(void) ++{ ++ int master, slave, status; ++ pid_t child; ++ ++ master = posix_openpt(O_RDWR | O_NOCTTY); ++ if (master < 0) ++ err(1, "posix_openpt"); ++ if (grantpt(master) < 0) ++ err(1, "grantpt"); ++ if (unlockpt(master) < 0) ++ err(1, "unlockpt"); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(3, "ioctl(TIOCSCTTY)"); ++ /* Detach ourselves from the controlling terminal. */ ++ if (ioctl(slave, TIOCNOTTY, 0) < 0) ++ err(4, "ioctl(TIOCNOTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ struct winsize winsz; ++ ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ /* Dereferences dangling t_pgrp pointer in the terminal. */ ++ memset(&winsz, 0xff, sizeof(winsz)); ++ if (ioctl(slave, TIOCSWINSZ, &winsz) < 0) ++ err(3, "ioctl(TIOCSWINSZ)"); ++ /* Dereferences dangling t_session pointer in the terminal. */ ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(4, "ioctl(TIOCSCTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++} diff --git a/website/static/security/patches/SA-26:10/tty-14.3.patch.asc b/website/static/security/patches/SA-26:10/tty-14.3.patch.asc new file mode 100644 index 0000000000..c3e58c7a64 --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-14.3.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoaYACgkQbljekB8A +Gu9pbQ/9GDR+iPv77e1nzCl2PNDRWftlTUIoh8Do3C4sHDG3nv1uMYOkdN4EINzE +ELxPaqgSCBSXQN8ehGAxNBUuSYhbdgjVE1bTTZ61sMpm6A0BsXeLMkZq5liI/1pp +T+qsh8ZvQbJDH5PWdgvUUb8mxvhs4DOP4F579hPckPFN3c9HYIpTMyTAjBMCsi0H +sMenxDMwei0SEA71nYr5bCFov6utUdqInb51hf6oE/zhf8dTgsFLye3PN4laDvfM +9kiapV6uWQqn+XH5Hg7c5P/6eHu6PMr8lCqxRwQeahKpmw1CcuRvtkJHhVBQYAqn +b5Wka6TBqC90Q0X9STahjWD7NmVLcD6Ly4e8+jzAeDt0GrYOSilQ2sSVdYrNJTRI +dnJctpeOUlLgLHAxctuwIwC/IohkEdtTtn/QbiZKdM12aPACm768DA+Gc5GVVukq +5HeSjcnSHIBBg7g5m/cWlNrr4Y8Kt1uFBRf9xet0k04qmlMGtAaYjmbtn1s/nGZi +PG9V1LyzDd5nj7feuWlkShzb7mLGaWIVFMnnu8MqhxcTeE89JGLLweaIPLR9Mic1 +ZPWPl6YB/hhHnR3VpyyboxPE2IYjrTFQV15uMIBLH0SCCUrNeCErUBtTRvVGbCD8 +X4a1jJ9xuIG36ljWg3S9poxZjxGsUcGzYvwsOEXiqvPzJrmH3UQ= +=q/W8 +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:10/tty-14.4.patch b/website/static/security/patches/SA-26:10/tty-14.4.patch new file mode 100644 index 0000000000..2b2df9b3df --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-14.4.patch @@ -0,0 +1,108 @@ +--- sys/kern/tty.c.orig ++++ sys/kern/tty.c +@@ -1262,6 +1262,10 @@ + session->s_ttydp = NULL; + SESS_UNLOCK(session); + ++ if (tp->t_session == session) { ++ tp->t_session = NULL; ++ tp->t_pgrp = NULL; ++ } + tp->t_sessioncnt--; + p->p_flag &= ~P_CONTROLT; + PROC_UNLOCK(p); +--- tests/sys/kern/tty/Makefile.orig ++++ tests/sys/kern/tty/Makefile +@@ -5,6 +5,7 @@ + PLAIN_TESTS_PORCH+= test_canon_fullbuf + PLAIN_TESTS_PORCH+= test_ncanon + PLAIN_TESTS_PORCH+= test_recanon ++PLAIN_TESTS_C+= tiocnotty + ATF_TESTS_C+= test_sti + + PROGS+= fionread +--- /dev/null ++++ tests/sys/kern/tty/tiocnotty.c +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org> ++ * ++ * SPDX-License-Identifier: BSD-2-Clause ++ */ ++ ++/* ++ * A regression test that exercises a bug where TIOCNOTTY would leave some ++ * dangling pointers behind in the controlling terminal structure. ++ */ ++ ++#include <sys/ioctl.h> ++#include <sys/wait.h> ++ ++#include <err.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++int ++main(void) ++{ ++ int master, slave, status; ++ pid_t child; ++ ++ master = posix_openpt(O_RDWR | O_NOCTTY); ++ if (master < 0) ++ err(1, "posix_openpt"); ++ if (grantpt(master) < 0) ++ err(1, "grantpt"); ++ if (unlockpt(master) < 0) ++ err(1, "unlockpt"); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(3, "ioctl(TIOCSCTTY)"); ++ /* Detach ourselves from the controlling terminal. */ ++ if (ioctl(slave, TIOCNOTTY, 0) < 0) ++ err(4, "ioctl(TIOCNOTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ struct winsize winsz; ++ ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ /* Dereferences dangling t_pgrp pointer in the terminal. */ ++ memset(&winsz, 0xff, sizeof(winsz)); ++ if (ioctl(slave, TIOCSWINSZ, &winsz) < 0) ++ err(3, "ioctl(TIOCSWINSZ)"); ++ /* Dereferences dangling t_session pointer in the terminal. */ ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(4, "ioctl(TIOCSCTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++} diff --git a/website/static/security/patches/SA-26:10/tty-14.4.patch.asc b/website/static/security/patches/SA-26:10/tty-14.4.patch.asc new file mode 100644 index 0000000000..fc58ad821d --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-14.4.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoacACgkQbljekB8A +Gu+C+Q/9G2j2xy3jibzA6BOGhW5P74e7d7Ew/iLh+9cLUMtOYkxbhhEe+iZoagFM +TfHgtBrZOYi1E3PrpI1dUyRCJocH7IpZgmQq1hQUlMjUWyycGWwjgqeIuv5D8qCJ +DP88551FmBDwE/WDdWFKoWWVraSWMDKG7GZVkGn60ahe77ICH4Ttck4OzxJMr3dv +3ixAUeYtyWGD3vCepB0CtDwsB5Y9cavFIVv5bnMeW8RYb6l872jYkOJUrySqhfiH +2fpbLRG07ULn+KaIPnonuY1i5UZV3tu7l1DWN2bDEyN4i17jXZI6zNQJYg6MPiUV +v3LT4RzV9tPzT98m341Ws+rNJ6T1X8gYCfNV+hx3Qq/yaCFruc9L+RxUnNEjJzxq +T5wGtU8FRQJGzzdH75zv7HGg/qL/5toHh9RfTU3g5AWd6F1TteUOTs7fj+06K6B/ +fRbDFg2sLaJUPVYYhM5GniWxOvYmKuahUCgIx1MHiLs7IJE/Yg70m/zBTlqIQAv7 +g9huqNu95WltJFmBuyXDG+o6BgA3EkN6wgcCbSpndSriFTIzmurguIrNXp+jx+4q +4pvPPb6UWr1EKr8b6EyCWkcTgqixOHZvUG3SN78tAAc6vzcabVIXh6dHPI7Pca+h +n1Za8e2ab1ECrBgBKVbrUqo7W11Pb5meT/390mPFfMPRGA41mbg= +=0SAa +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:10/tty-15.patch b/website/static/security/patches/SA-26:10/tty-15.patch new file mode 100644 index 0000000000..660e6dd58b --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-15.patch @@ -0,0 +1,108 @@ +--- sys/kern/tty.c.orig ++++ sys/kern/tty.c +@@ -1263,6 +1263,10 @@ + session->s_ttydp = NULL; + SESS_UNLOCK(session); + ++ if (tp->t_session == session) { ++ tp->t_session = NULL; ++ tp->t_pgrp = NULL; ++ } + tp->t_sessioncnt--; + p->p_flag &= ~P_CONTROLT; + PROC_UNLOCK(p); +--- tests/sys/kern/tty/Makefile.orig ++++ tests/sys/kern/tty/Makefile +@@ -5,6 +5,7 @@ + PLAIN_TESTS_PORCH+= test_canon_fullbuf + PLAIN_TESTS_PORCH+= test_ncanon + PLAIN_TESTS_PORCH+= test_recanon ++PLAIN_TESTS_C+= tiocnotty + ATF_TESTS_C+= test_sti + + PROGS+= fionread +--- /dev/null ++++ tests/sys/kern/tty/tiocnotty.c +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org> ++ * ++ * SPDX-License-Identifier: BSD-2-Clause ++ */ ++ ++/* ++ * A regression test that exercises a bug where TIOCNOTTY would leave some ++ * dangling pointers behind in the controlling terminal structure. ++ */ ++ ++#include <sys/ioctl.h> ++#include <sys/wait.h> ++ ++#include <err.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++int ++main(void) ++{ ++ int master, slave, status; ++ pid_t child; ++ ++ master = posix_openpt(O_RDWR | O_NOCTTY); ++ if (master < 0) ++ err(1, "posix_openpt"); ++ if (grantpt(master) < 0) ++ err(1, "grantpt"); ++ if (unlockpt(master) < 0) ++ err(1, "unlockpt"); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(3, "ioctl(TIOCSCTTY)"); ++ /* Detach ourselves from the controlling terminal. */ ++ if (ioctl(slave, TIOCNOTTY, 0) < 0) ++ err(4, "ioctl(TIOCNOTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++ ++ child = fork(); ++ if (child < 0) ++ err(1, "fork"); ++ if (child == 0) { ++ struct winsize winsz; ++ ++ if (setsid() < 0) ++ err(1, "setsid"); ++ slave = open(ptsname(master), O_RDWR | O_NOCTTY); ++ if (slave < 0) ++ err(2, "open"); ++ /* Dereferences dangling t_pgrp pointer in the terminal. */ ++ memset(&winsz, 0xff, sizeof(winsz)); ++ if (ioctl(slave, TIOCSWINSZ, &winsz) < 0) ++ err(3, "ioctl(TIOCSWINSZ)"); ++ /* Dereferences dangling t_session pointer in the terminal. */ ++ if (ioctl(slave, TIOCSCTTY, 0) < 0) ++ err(4, "ioctl(TIOCSCTTY)"); ++ _exit(0); ++ } ++ ++ if (waitpid(child, &status, 0) < 0) ++ err(1, "waitpid"); ++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ errx(1, "child exited with status %d", WEXITSTATUS(status)); ++} diff --git a/website/static/security/patches/SA-26:10/tty-15.patch.asc b/website/static/security/patches/SA-26:10/tty-15.patch.asc new file mode 100644 index 0000000000..f4d6c1e912 --- /dev/null +++ b/website/static/security/patches/SA-26:10/tty-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoagACgkQbljekB8A +Gu/GWQ//YLLyJhu4UoYYN/4p/Up+F9s3dyfhRvO6qnCERdnT8nS+ZZ1/oYozvVv9 +d8GYaSx+8u1kfdD/U0D9515TWygISBhJBIZNAhcILAr0Z9drtOZ4LH0PAHjEToHZ +6DLb5zjwuHJGeFwranMuNMOAeGq5uKGjgSOsq5ZEC1644kUxA0Eb1n76pI/JC8DM +ciYJLHNz5LpfymZDDp6kcpyN4W9aylwH9C5yVn+pGCuGVAeW6QtLgYnM+LIyMC7L +WuFTQdVOKI7B/7Gy/R7N/rfIYcyVtyf7oqtt4bSknQxs1KEn7GUfLZxyRS2KntSi +swpaMN8x1pdEdJGdQ7ldl1sYtEKeFTlWX0DZunR4yJT+xKR/PV3t7sgBwQwF1ebh +BLdadJVSXMCAkzdifl8lmpgyU9IOcyFEv9KbmjTE2bKY6ob9Tzq/y3yCuWRKCpbc +dcBOxRo6voNrssp6oNJpN6TFFmtgkH69RiKwOKtzJfgjgfUUEqGktmB96cpGstwG +vFwiUPjDSfvJ57WTZpsvHaNjPQrlmOniKlpnk8ilpDkX5AOtcOnW+l3vUBzBHMzq +NIgnjU6i/SSN1L0mEqGjhbYay7DZc0U284SIpmPa4wxnti4AQOr+ADHH93uQehKm +8BPnYKXzz2+MdvKDjGaOcHGwtkYojOhpIggwy/9a9cdPo2PhvaY= +=QZql +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:11/amd64-13.patch b/website/static/security/patches/SA-26:11/amd64-13.patch new file mode 100644 index 0000000000..95b97f6e79 --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-13.patch @@ -0,0 +1,397 @@ +--- lib/libc/x86/sys/pkru.3.orig ++++ lib/libc/x86/sys/pkru.3 +@@ -179,6 +179,9 @@ + argument for + .Fn x86_pkru_protect_range + has reserved bits set. ++.It Bq Er EINVAL ++The range of the request partially covers a mapping of an object created by ++.Xr shm_create_largepage 3 . + .It Bq Er EFAULT + The supplied address range does not completely fit into the user-managed + address range. +--- sys/amd64/amd64/pmap.c.orig ++++ sys/amd64/amd64/pmap.c +@@ -11255,7 +11255,7 @@ + u_int keyidx) + { + pml4_entry_t *pml4e; +- pdp_entry_t *pdpe; ++ pdp_entry_t newpdpe, *pdpe; + pd_entry_t newpde, ptpaddr, *pde; + pt_entry_t newpte, *ptep, pte; + vm_offset_t va, va_next; +@@ -11281,6 +11281,22 @@ + va_next = eva; + continue; + } ++ if ((*pdpe & PG_PS) != 0) { ++ va_next = (va + NBPDP) & ~PDPMASK; ++ if (va_next < va) ++ va_next = eva; ++ KASSERT(va_next <= eva, ++ ("partial update of non-transparent 1G mapping " ++ "pdpe %#lx va %#lx eva %#lx va_next %#lx", ++ *pdpe, va, eva, va_next)); ++ newpdpe = (*pdpe & ~X86_PG_PKU_MASK) | ++ X86_PG_PKU(keyidx); ++ if (newpdpe != *pdpe) { ++ *pdpe = newpdpe; ++ changed = true; ++ } ++ continue; ++ } + + va_next = (va + NBPDR) & ~PDRMASK; + if (va_next < va) +@@ -11333,8 +11349,6 @@ + if (pmap->pm_type != PT_X86 || keyidx > PMAP_MAX_PKRU_IDX || + (flags & ~(AMD64_PKRU_PERSIST | AMD64_PKRU_EXCL)) != 0) + return (EINVAL); +- if (eva <= sva || eva > VM_MAXUSER_ADDRESS) +- return (EFAULT); + if ((cpu_stdext_feature2 & CPUID_STDEXT2_PKU) == 0) + return (ENOTSUP); + return (0); +--- sys/amd64/amd64/sys_machdep.c.orig ++++ sys/amd64/amd64/sys_machdep.c +@@ -32,7 +32,6 @@ + * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + */ + +-#include <sys/cdefs.h> + #include "opt_capsicum.h" + #include "opt_ktrace.h" + +@@ -356,32 +355,58 @@ + break; + + case I386_SET_PKRU: +- case AMD64_SET_PKRU: ++ case AMD64_SET_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + /* + * Read-lock the map to synchronize with parallel + * pmap_vmspace_copy() on fork. + */ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_set(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, (vm_offset_t)a64pkru.addr + +- a64pkru.len, a64pkru.keyidx, a64pkru.flags); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_set(PCPU_GET(curpmap), start, end, ++ a64pkru.keyidx, a64pkru.flags); + vm_map_unlock_read(map); + break; ++ } + + case I386_CLEAR_PKRU: +- case AMD64_CLEAR_PKRU: ++ case AMD64_CLEAR_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ + if (a64pkru.flags != 0 || a64pkru.keyidx != 0) { + error = EINVAL; + break; + } ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_clear(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, +- (vm_offset_t)a64pkru.addr + a64pkru.len); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_clear(PCPU_GET(curpmap), start, end); + vm_map_unlock_read(map); + break; ++ } + + default: + error = EINVAL; +--- sys/vm/vm_map.c.orig ++++ sys/vm/vm_map.c +@@ -4116,6 +4116,38 @@ + return (TRUE); + } + ++/* ++ * Check whether the specified range partially overlaps a map entry with ++ * fixed boundaries, and return false if so. ++ * ++ * The map must be locked. ++ */ ++bool ++vm_map_check_boundary(vm_map_t map, vm_offset_t start, vm_offset_t end) ++{ ++ vm_map_entry_t entry; ++ int bdry_idx; ++ ++ if (!vm_map_range_valid(map, start, end)) ++ return (false); ++ if (start == end) ++ return (true); ++ ++ if (vm_map_lookup_entry(map, start, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (start & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ if (vm_map_lookup_entry(map, end - 1, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (end & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ return (true); ++} ++ + /* + * + * vm_map_copy_swap_object: +--- sys/vm/vm_map.h.orig ++++ sys/vm/vm_map.h +@@ -469,6 +469,7 @@ + #endif /* ! _KERNEL */ + + #ifdef _KERNEL ++bool vm_map_check_boundary(vm_map_t, vm_offset_t, vm_offset_t); + boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); + int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t); + int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, +--- tests/sys/posixshm/posixshm_test.c.orig ++++ tests/sys/posixshm/posixshm_test.c +@@ -34,10 +34,17 @@ + #include <sys/sysctl.h> + #include <sys/wait.h> + ++#ifdef __amd64__ ++#include <machine/sysarch.h> ++#endif ++ + #include <ctype.h> + #include <errno.h> + #include <fcntl.h> ++#include <paths.h> ++#include <setjmp.h> + #include <signal.h> ++#include <stdatomic.h> + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +@@ -1702,6 +1709,183 @@ + } + } + ++#ifdef __amd64__ ++static sigjmp_buf jmpbuf; ++static _Atomic(void *) faultaddr; ++static _Atomic(int) faultsig; ++ ++#define KEY_RW 1 ++#define KEY_RO 2 ++#define KEY_WO 3 ++#define KEY_NO 4 ++#define VAL 0xdeadfacec0debeef ++static void ++set_keys(void) ++{ ++ int error; ++ ++ error = x86_pkru_set_perm(KEY_RW, 1, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_RO, 1, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_WO, 0, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_NO, 0, 0); ++ ATF_REQUIRE(error == 0); ++} ++ ++static void ++sigsegv(int sig, siginfo_t *si, void *uc __unused) ++{ ++ faultsig = sig; ++ faultaddr = si->si_addr; ++ siglongjmp(jmpbuf, 1); ++} ++ ++static bool ++try_read(volatile uint64_t *p, uint64_t *outp) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *outp = *p; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++static bool ++try_write(volatile uint64_t *p, uint64_t val) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *p = val; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++ATF_TC_WITHOUT_HEAD(largepage_pkru); ++ATF_TC_BODY(largepage_pkru, tc) ++{ ++ size_t ps[MAXPAGESIZES]; ++ struct sigaction sa; ++ char *addr, *addr1; ++ int error, fd, pscnt; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.sa_sigaction = sigsegv; ++ sa.sa_flags = SA_SIGINFO; ++ sigemptyset(&sa.sa_mask); ++ error = sigaction(SIGSEGV, &sa, NULL); ++ ATF_REQUIRE(error == 0); ++ ++ pscnt = pagesizes(ps); ++ ++ for (int i = 1; i < pscnt; i++) { ++ uint64_t val; ++ ++ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); ++ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, ++ 0); ++ ATF_REQUIRE_MSG(addr != MAP_FAILED, ++ "mmap(%zu bytes) failed; error=%d", ps[i], errno); ++ ++ /* ++ * Ensure that the page is faulted into the pmap. ++ */ ++ memset(addr, 0, ps[i]); ++ ++ set_keys(); ++ ++ /* ++ * Make sure we can't partially cover a largepage mapping. ++ */ ++ error = x86_pkru_protect_range(addr, PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr, ps[i] - PAGE_SIZE, KEY_RW, ++ 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ps[i] - PAGE_SIZE, ++ KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + 1, ps[i], KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ ++ /* ++ * Make sure that protections are honoured. ++ */ ++ for (int j = 1; j <= 4; j++) { ++ volatile uint64_t *addr64; ++ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr64 = (volatile uint64_t *)(void *)addr; ++ *addr64 = VAL; ++ ++ error = x86_pkru_protect_range(addr, ps[i], j, 0); ++ ATF_REQUIRE(error == 0); ++ switch (j) { ++ case KEY_RW: ++ ATF_REQUIRE(try_write(addr64, VAL)); ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ break; ++ case KEY_RO: ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ case KEY_WO: ++ /* !access implies !modify */ ++ case KEY_NO: ++ ATF_REQUIRE(!try_read(addr64, &val)); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ default: ++ __unreachable(); ++ } ++ } ++ error = munmap(addr, ps[i]); ++ ATF_CHECK(error == 0); ++ ++ /* ++ * Try mapping a large page in a region partially covered by a ++ * key. ++ * ++ * Rather than detecting the mismatch when the logical mapping ++ * is created, we currently only fail once pmap_enter() is ++ * called from the fault handler. This is not ideal and might ++ * be improved in the future. ++ */ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ++ ps[i] - PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_FIXED, fd, 0); ++ ATF_REQUIRE(addr1 != MAP_FAILED); ++ ATF_REQUIRE(addr == addr1); ++ ATF_REQUIRE(!try_read((volatile uint64_t *)(void *)addr, &val)); ++ ATF_REQUIRE(!try_write((volatile uint64_t *)(void *)addr, VAL)); ++ } ++} ++#undef KEY_RW ++#undef KEY_RO ++#undef KEY_WO ++#undef KEY_NO ++#endif ++ + ATF_TC_WITHOUT_HEAD(largepage_reopen); + ATF_TC_BODY(largepage_reopen, tc) + { +@@ -1791,6 +1975,9 @@ + ATF_TP_ADD_TC(tp, largepage_mprotect); + ATF_TP_ADD_TC(tp, largepage_minherit); + ATF_TP_ADD_TC(tp, largepage_pipe); ++#ifdef __amd64__ ++ ATF_TP_ADD_TC(tp, largepage_pkru); ++#endif + ATF_TP_ADD_TC(tp, largepage_reopen); + + return (atf_no_error()); diff --git a/website/static/security/patches/SA-26:11/amd64-13.patch.asc b/website/static/security/patches/SA-26:11/amd64-13.patch.asc new file mode 100644 index 0000000000..afc74bab6b --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-13.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoasACgkQbljekB8A +Gu+hSBAAn7ymG70uRhOZuB/b3yO6Wa7NBAMPX6JslR97Er2MVWkgRwLEWf9vDutn +o7vXt5KcqocJO/YjJJSyMyCkkLykIu+Ak7tCmQL6TohwnYoRNiXgKOnWvKv4YoKp +0MMrULLANIf1aVZDHcuBYNbp84OZiLkdHwkNVY2j62+Pt3ghHSDb6xhSlw9EY816 +yJ4GdJpcPXfruglnbJQG4j/Gg/M2iAYp5Z5Do6/zDrQ/oM76H9RhX4+Crp57iZRD +vVYmrHAfNzG3Gmmk5W8NLLe8Ys03rUXizhqrLCYbiEbyHIil0NWqzSPBVO6fJFPM +TBsAAd8ym1S65HLp/PzQJHkPNyCoT5PR3b+u65FDX/iJDFJWS9zEtr/Mem6LFkZL +vCrK2GLkW31dCT3bKGHEXTpKRWBobWXBfpYYy9RZR9p1n0kfGVvvHZNvFZpBar/F +UAIzpFMb0wS1k7Njw7GeOl3AQPinj1zZcoGijEVb1a9RUyq9oTMMVqpAViunRoOT +Vzq3WOfaj6byRq6+8xYf6sHwT1nAXxxQoqVxMKGG5E0Np2BCwKvrgSUEGM80k3aA +rjEJk65DIW0wK1vuTg9Wzlz3ocybvguKT6JHd410gTymi3pQwg0TEmIqQX/pHyU9 +4zmCRqgWOr6urcg1RxkCWYqCkKgYK6U2Iw35Fh5XUbXfPPckGAo= +=Vdvx +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:11/amd64-14.patch b/website/static/security/patches/SA-26:11/amd64-14.patch new file mode 100644 index 0000000000..90a95516f8 --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-14.patch @@ -0,0 +1,397 @@ +--- lib/libc/x86/sys/pkru.3.orig ++++ lib/libc/x86/sys/pkru.3 +@@ -179,6 +179,9 @@ + argument for + .Fn x86_pkru_protect_range + has reserved bits set. ++.It Bq Er EINVAL ++The range of the request partially covers a mapping of an object created by ++.Xr shm_create_largepage 3 . + .It Bq Er EFAULT + The supplied address range does not completely fit into the user-managed + address range. +--- sys/amd64/amd64/pmap.c.orig ++++ sys/amd64/amd64/pmap.c +@@ -11598,7 +11598,7 @@ + u_int keyidx) + { + pml4_entry_t *pml4e; +- pdp_entry_t *pdpe; ++ pdp_entry_t newpdpe, *pdpe; + pd_entry_t newpde, ptpaddr, *pde; + pt_entry_t newpte, *ptep, pte; + vm_offset_t va, va_next; +@@ -11624,6 +11624,22 @@ + va_next = eva; + continue; + } ++ if ((*pdpe & PG_PS) != 0) { ++ va_next = (va + NBPDP) & ~PDPMASK; ++ if (va_next < va) ++ va_next = eva; ++ KASSERT(va_next <= eva, ++ ("partial update of non-transparent 1G mapping " ++ "pdpe %#lx va %#lx eva %#lx va_next %#lx", ++ *pdpe, va, eva, va_next)); ++ newpdpe = (*pdpe & ~X86_PG_PKU_MASK) | ++ X86_PG_PKU(keyidx); ++ if (newpdpe != *pdpe) { ++ *pdpe = newpdpe; ++ changed = true; ++ } ++ continue; ++ } + + va_next = (va + NBPDR) & ~PDRMASK; + if (va_next < va) +@@ -11676,8 +11692,6 @@ + if (pmap->pm_type != PT_X86 || keyidx > PMAP_MAX_PKRU_IDX || + (flags & ~(AMD64_PKRU_PERSIST | AMD64_PKRU_EXCL)) != 0) + return (EINVAL); +- if (eva <= sva || eva > VM_MAXUSER_ADDRESS) +- return (EFAULT); + if ((cpu_stdext_feature2 & CPUID_STDEXT2_PKU) == 0) + return (ENOTSUP); + return (0); +--- sys/amd64/amd64/sys_machdep.c.orig ++++ sys/amd64/amd64/sys_machdep.c +@@ -32,7 +32,6 @@ + * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + */ + +-#include <sys/cdefs.h> + #include "opt_capsicum.h" + #include "opt_ktrace.h" + +@@ -371,32 +370,58 @@ + break; + + case I386_SET_PKRU: +- case AMD64_SET_PKRU: ++ case AMD64_SET_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + /* + * Read-lock the map to synchronize with parallel + * pmap_vmspace_copy() on fork. + */ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_set(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, (vm_offset_t)a64pkru.addr + +- a64pkru.len, a64pkru.keyidx, a64pkru.flags); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_set(PCPU_GET(curpmap), start, end, ++ a64pkru.keyidx, a64pkru.flags); + vm_map_unlock_read(map); + break; ++ } + + case I386_CLEAR_PKRU: +- case AMD64_CLEAR_PKRU: ++ case AMD64_CLEAR_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ + if (a64pkru.flags != 0 || a64pkru.keyidx != 0) { + error = EINVAL; + break; + } ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_clear(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, +- (vm_offset_t)a64pkru.addr + a64pkru.len); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_clear(PCPU_GET(curpmap), start, end); + vm_map_unlock_read(map); + break; ++ } + + case AMD64_DISABLE_TLSBASE: + clear_pcb_flags(pcb, PCB_TLSBASE); +--- sys/vm/vm_map.c.orig ++++ sys/vm/vm_map.c +@@ -4140,6 +4140,38 @@ + return (TRUE); + } + ++/* ++ * Check whether the specified range partially overlaps a map entry with ++ * fixed boundaries, and return false if so. ++ * ++ * The map must be locked. ++ */ ++bool ++vm_map_check_boundary(vm_map_t map, vm_offset_t start, vm_offset_t end) ++{ ++ vm_map_entry_t entry; ++ int bdry_idx; ++ ++ if (!vm_map_range_valid(map, start, end)) ++ return (false); ++ if (start == end) ++ return (true); ++ ++ if (vm_map_lookup_entry(map, start, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (start & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ if (vm_map_lookup_entry(map, end - 1, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (end & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ return (true); ++} ++ + /* + * + * vm_map_copy_swap_object: +--- sys/vm/vm_map.h.orig ++++ sys/vm/vm_map.h +@@ -471,6 +471,7 @@ + #endif /* ! _KERNEL */ + + #ifdef _KERNEL ++bool vm_map_check_boundary(vm_map_t, vm_offset_t, vm_offset_t); + boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); + int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t); + int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, +--- tests/sys/posixshm/posixshm_test.c.orig ++++ tests/sys/posixshm/posixshm_test.c +@@ -39,10 +39,17 @@ + #include <sys/sysctl.h> + #include <sys/wait.h> + ++#ifdef __amd64__ ++#include <machine/sysarch.h> ++#endif ++ + #include <ctype.h> + #include <errno.h> + #include <fcntl.h> ++#include <paths.h> ++#include <setjmp.h> + #include <signal.h> ++#include <stdatomic.h> + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +@@ -1902,6 +1909,183 @@ + } + } + ++#ifdef __amd64__ ++static sigjmp_buf jmpbuf; ++static _Atomic(void *) faultaddr; ++static _Atomic(int) faultsig; ++ ++#define KEY_RW 1 ++#define KEY_RO 2 ++#define KEY_WO 3 ++#define KEY_NO 4 ++#define VAL 0xdeadfacec0debeef ++static void ++set_keys(void) ++{ ++ int error; ++ ++ error = x86_pkru_set_perm(KEY_RW, 1, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_RO, 1, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_WO, 0, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_NO, 0, 0); ++ ATF_REQUIRE(error == 0); ++} ++ ++static void ++sigsegv(int sig, siginfo_t *si, void *uc __unused) ++{ ++ faultsig = sig; ++ faultaddr = si->si_addr; ++ siglongjmp(jmpbuf, 1); ++} ++ ++static bool ++try_read(volatile uint64_t *p, uint64_t *outp) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *outp = *p; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++static bool ++try_write(volatile uint64_t *p, uint64_t val) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *p = val; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++ATF_TC_WITHOUT_HEAD(largepage_pkru); ++ATF_TC_BODY(largepage_pkru, tc) ++{ ++ size_t ps[MAXPAGESIZES]; ++ struct sigaction sa; ++ char *addr, *addr1; ++ int error, fd, pscnt; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.sa_sigaction = sigsegv; ++ sa.sa_flags = SA_SIGINFO; ++ sigemptyset(&sa.sa_mask); ++ error = sigaction(SIGSEGV, &sa, NULL); ++ ATF_REQUIRE(error == 0); ++ ++ pscnt = pagesizes(ps); ++ ++ for (int i = 1; i < pscnt; i++) { ++ uint64_t val; ++ ++ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); ++ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, ++ 0); ++ ATF_REQUIRE_MSG(addr != MAP_FAILED, ++ "mmap(%zu bytes) failed; error=%d", ps[i], errno); ++ ++ /* ++ * Ensure that the page is faulted into the pmap. ++ */ ++ memset(addr, 0, ps[i]); ++ ++ set_keys(); ++ ++ /* ++ * Make sure we can't partially cover a largepage mapping. ++ */ ++ error = x86_pkru_protect_range(addr, PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr, ps[i] - PAGE_SIZE, KEY_RW, ++ 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ps[i] - PAGE_SIZE, ++ KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + 1, ps[i], KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ ++ /* ++ * Make sure that protections are honoured. ++ */ ++ for (int j = 1; j <= 4; j++) { ++ volatile uint64_t *addr64; ++ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr64 = (volatile uint64_t *)(void *)addr; ++ *addr64 = VAL; ++ ++ error = x86_pkru_protect_range(addr, ps[i], j, 0); ++ ATF_REQUIRE(error == 0); ++ switch (j) { ++ case KEY_RW: ++ ATF_REQUIRE(try_write(addr64, VAL)); ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ break; ++ case KEY_RO: ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ case KEY_WO: ++ /* !access implies !modify */ ++ case KEY_NO: ++ ATF_REQUIRE(!try_read(addr64, &val)); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ default: ++ __unreachable(); ++ } ++ } ++ error = munmap(addr, ps[i]); ++ ATF_CHECK(error == 0); ++ ++ /* ++ * Try mapping a large page in a region partially covered by a ++ * key. ++ * ++ * Rather than detecting the mismatch when the logical mapping ++ * is created, we currently only fail once pmap_enter() is ++ * called from the fault handler. This is not ideal and might ++ * be improved in the future. ++ */ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ++ ps[i] - PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_FIXED, fd, 0); ++ ATF_REQUIRE(addr1 != MAP_FAILED); ++ ATF_REQUIRE(addr == addr1); ++ ATF_REQUIRE(!try_read((volatile uint64_t *)(void *)addr, &val)); ++ ATF_REQUIRE(!try_write((volatile uint64_t *)(void *)addr, VAL)); ++ } ++} ++#undef KEY_RW ++#undef KEY_RO ++#undef KEY_WO ++#undef KEY_NO ++#endif ++ + ATF_TC_WITHOUT_HEAD(largepage_reopen); + ATF_TC_BODY(largepage_reopen, tc) + { +@@ -1992,6 +2176,9 @@ + ATF_TP_ADD_TC(tp, largepage_mprotect); + ATF_TP_ADD_TC(tp, largepage_minherit); + ATF_TP_ADD_TC(tp, largepage_pipe); ++#ifdef __amd64__ ++ ATF_TP_ADD_TC(tp, largepage_pkru); ++#endif + ATF_TP_ADD_TC(tp, largepage_reopen); + + return (atf_no_error()); diff --git a/website/static/security/patches/SA-26:11/amd64-14.patch.asc b/website/static/security/patches/SA-26:11/amd64-14.patch.asc new file mode 100644 index 0000000000..84857f46a1 --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-14.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoawACgkQbljekB8A +Gu/iIhAApnDKPpojyoXKgdTxG8nQMRAZOj5uiMmAHrGMMMhmh8TzhGfhlSeyYrp2 +oxEQlrutS7HEkyPDfN4mcE4OLWZH2vMqEWYx3fA73RvsWkocCreiDVqdx8uFn3Wy +TjkH1Ju+1pJCsLsircFEArb/3mQ7qNMw0NbqJTHt/f3Iv9KdW7U07RD4YCy7J6wf +tqGiIHfmq8s23+2rzTf+/JaSskkTMkNAM4jv+aCQ9qkenADk0eZPXD8dXIeNKL4T +7K1IqYhGNg9Njyqpg39NM4pcFoyD4r4snbBZolcx3XyepMR8w4koJVDAuauo4I3d +nNwEP7aJ4Z6Fiv0H7bOwJdLYw5BD+DJsQ4DaY7CpSpzQmRF/wrHtK0BFu1Nhkq3p +T70BIRdOE0tuEF87AQDdGmIdbNywgOuQmzVI526g4CKqVmdtX389Tfhvfy0N5VpB +H4PfgGNuIWx2liRnKcjdGTSywxo/B2+NlcgUpC3QOm0Y3i2/OZPM850UJ0IBNG6r +hn4Vr7gJLAQ/bMA2SsBD+jtI1kiK5qelx2E7dVND3DCXIItIn+ljFNgU8qtYuz/D +exmoYFp0djkm5Ap4BXHxDOLZyln8lNlzlJJfP+v89IgBen2HTDAFMEm/5GgoIpgT +FRXM+X9sCqrgaimpUnmQKueFQGZS8J1+Rh3O2x46PV818Hem68Q= +=qZnW +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:11/amd64-15.patch b/website/static/security/patches/SA-26:11/amd64-15.patch new file mode 100644 index 0000000000..4f894028f1 --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-15.patch @@ -0,0 +1,397 @@ +--- lib/libsys/x86/pkru.3.orig ++++ lib/libsys/x86/pkru.3 +@@ -179,6 +179,9 @@ + argument for + .Fn x86_pkru_protect_range + has reserved bits set. ++.It Bq Er EINVAL ++The range of the request partially covers a mapping of an object created by ++.Xr shm_create_largepage 3 . + .It Bq Er EFAULT + The supplied address range does not completely fit into the user-managed + address range. +--- sys/amd64/amd64/pmap.c.orig ++++ sys/amd64/amd64/pmap.c +@@ -11551,7 +11551,7 @@ + u_int keyidx) + { + pml4_entry_t *pml4e; +- pdp_entry_t *pdpe; ++ pdp_entry_t newpdpe, *pdpe; + pd_entry_t newpde, ptpaddr, *pde; + pt_entry_t newpte, *ptep, pte; + vm_offset_t va, va_next; +@@ -11577,6 +11577,22 @@ + va_next = eva; + continue; + } ++ if ((*pdpe & PG_PS) != 0) { ++ va_next = (va + NBPDP) & ~PDPMASK; ++ if (va_next < va) ++ va_next = eva; ++ KASSERT(va_next <= eva, ++ ("partial update of non-transparent 1G mapping " ++ "pdpe %#lx va %#lx eva %#lx va_next %#lx", ++ *pdpe, va, eva, va_next)); ++ newpdpe = (*pdpe & ~X86_PG_PKU_MASK) | ++ X86_PG_PKU(keyidx); ++ if (newpdpe != *pdpe) { ++ *pdpe = newpdpe; ++ changed = true; ++ } ++ continue; ++ } + + va_next = (va + NBPDR) & ~PDRMASK; + if (va_next < va) +@@ -11629,8 +11645,6 @@ + if (pmap->pm_type != PT_X86 || keyidx > PMAP_MAX_PKRU_IDX || + (flags & ~(AMD64_PKRU_PERSIST | AMD64_PKRU_EXCL)) != 0) + return (EINVAL); +- if (eva <= sva || eva > VM_MAXUSER_ADDRESS) +- return (EFAULT); + if ((cpu_stdext_feature2 & CPUID_STDEXT2_PKU) == 0) + return (ENOTSUP); + return (0); +--- sys/amd64/amd64/sys_machdep.c.orig ++++ sys/amd64/amd64/sys_machdep.c +@@ -30,7 +30,6 @@ + * SUCH DAMAGE. + */ + +-#include <sys/cdefs.h> + #include "opt_capsicum.h" + #include "opt_ktrace.h" + +@@ -369,32 +368,58 @@ + break; + + case I386_SET_PKRU: +- case AMD64_SET_PKRU: ++ case AMD64_SET_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + /* + * Read-lock the map to synchronize with parallel + * pmap_vmspace_copy() on fork. + */ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_set(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, (vm_offset_t)a64pkru.addr + +- a64pkru.len, a64pkru.keyidx, a64pkru.flags); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_set(PCPU_GET(curpmap), start, end, ++ a64pkru.keyidx, a64pkru.flags); + vm_map_unlock_read(map); + break; ++ } + + case I386_CLEAR_PKRU: +- case AMD64_CLEAR_PKRU: ++ case AMD64_CLEAR_PKRU: { ++ vm_offset_t addr, start, end; ++ vm_size_t len; ++ + if (a64pkru.flags != 0 || a64pkru.keyidx != 0) { + error = EINVAL; + break; + } ++ ++ addr = (uintptr_t)a64pkru.addr; ++ len = a64pkru.len; ++ + map = &td->td_proc->p_vmspace->vm_map; + vm_map_lock_read(map); +- error = pmap_pkru_clear(PCPU_GET(curpmap), +- (vm_offset_t)a64pkru.addr, +- (vm_offset_t)a64pkru.addr + a64pkru.len); ++ if (len == 0 || !vm_map_check_boundary(map, addr, addr + len)) { ++ vm_map_unlock_read(map); ++ error = EINVAL; ++ break; ++ } ++ start = trunc_page(addr); ++ end = round_page(addr + len); ++ error = pmap_pkru_clear(PCPU_GET(curpmap), start, end); + vm_map_unlock_read(map); + break; ++ } + + case AMD64_DISABLE_TLSBASE: + clear_pcb_flags(pcb, PCB_TLSBASE); +--- sys/vm/vm_map.c.orig ++++ sys/vm/vm_map.c +@@ -4162,6 +4162,38 @@ + return (TRUE); + } + ++/* ++ * Check whether the specified range partially overlaps a map entry with ++ * fixed boundaries, and return false if so. ++ * ++ * The map must be locked. ++ */ ++bool ++vm_map_check_boundary(vm_map_t map, vm_offset_t start, vm_offset_t end) ++{ ++ vm_map_entry_t entry; ++ int bdry_idx; ++ ++ if (!vm_map_range_valid(map, start, end)) ++ return (false); ++ if (start == end) ++ return (true); ++ ++ if (vm_map_lookup_entry(map, start, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (start & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ if (vm_map_lookup_entry(map, end - 1, &entry)) { ++ bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry); ++ if (bdry_idx != 0 && ++ (end & (pagesizes[bdry_idx] - 1)) != 0) ++ return (false); ++ } ++ return (true); ++} ++ + /* + * + * vm_map_copy_swap_object: +--- sys/vm/vm_map.h.orig ++++ sys/vm/vm_map.h +@@ -479,6 +479,7 @@ + #endif /* ! _KERNEL */ + + #ifdef _KERNEL ++bool vm_map_check_boundary(vm_map_t, vm_offset_t, vm_offset_t); + boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); + int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t); + int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, +--- tests/sys/posixshm/posixshm_test.c.orig ++++ tests/sys/posixshm/posixshm_test.c +@@ -38,10 +38,17 @@ + #include <sys/sysctl.h> + #include <sys/wait.h> + ++#ifdef __amd64__ ++#include <machine/sysarch.h> ++#endif ++ + #include <ctype.h> + #include <errno.h> + #include <fcntl.h> ++#include <paths.h> ++#include <setjmp.h> + #include <signal.h> ++#include <stdatomic.h> + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +@@ -1889,6 +1896,183 @@ + } + } + ++#ifdef __amd64__ ++static sigjmp_buf jmpbuf; ++static _Atomic(void *) faultaddr; ++static _Atomic(int) faultsig; ++ ++#define KEY_RW 1 ++#define KEY_RO 2 ++#define KEY_WO 3 ++#define KEY_NO 4 ++#define VAL 0xdeadfacec0debeef ++static void ++set_keys(void) ++{ ++ int error; ++ ++ error = x86_pkru_set_perm(KEY_RW, 1, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_RO, 1, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_WO, 0, 1); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_set_perm(KEY_NO, 0, 0); ++ ATF_REQUIRE(error == 0); ++} ++ ++static void ++sigsegv(int sig, siginfo_t *si, void *uc __unused) ++{ ++ faultsig = sig; ++ faultaddr = si->si_addr; ++ siglongjmp(jmpbuf, 1); ++} ++ ++static bool ++try_read(volatile uint64_t *p, uint64_t *outp) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *outp = *p; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++static bool ++try_write(volatile uint64_t *p, uint64_t val) ++{ ++ if (sigsetjmp(jmpbuf, 1) == 0) { ++ *p = val; ++ return (true); ++ } else { ++ atomic_signal_fence(memory_order_relaxed); ++ ATF_REQUIRE(faultsig == SIGSEGV); ++ ATF_REQUIRE(faultaddr == p); ++ set_keys(); /* PKRU is not restored by siglongjmp? */ ++ return (false); ++ } ++} ++ ++ATF_TC_WITHOUT_HEAD(largepage_pkru); ++ATF_TC_BODY(largepage_pkru, tc) ++{ ++ size_t ps[MAXPAGESIZES]; ++ struct sigaction sa; ++ char *addr, *addr1; ++ int error, fd, pscnt; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.sa_sigaction = sigsegv; ++ sa.sa_flags = SA_SIGINFO; ++ sigemptyset(&sa.sa_mask); ++ error = sigaction(SIGSEGV, &sa, NULL); ++ ATF_REQUIRE(error == 0); ++ ++ pscnt = pagesizes(ps, true); ++ ++ for (int i = 1; i < pscnt; i++) { ++ uint64_t val; ++ ++ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); ++ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, ++ 0); ++ ATF_REQUIRE_MSG(addr != MAP_FAILED, ++ "mmap(%zu bytes) failed; error=%d", ps[i], errno); ++ ++ /* ++ * Ensure that the page is faulted into the pmap. ++ */ ++ memset(addr, 0, ps[i]); ++ ++ set_keys(); ++ ++ /* ++ * Make sure we can't partially cover a largepage mapping. ++ */ ++ error = x86_pkru_protect_range(addr, PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr, ps[i] - PAGE_SIZE, KEY_RW, ++ 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ps[i] - PAGE_SIZE, ++ KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ error = x86_pkru_protect_range(addr + 1, ps[i], KEY_RW, 0); ++ ATF_REQUIRE_ERRNO(EINVAL, error != 0); ++ ++ /* ++ * Make sure that protections are honoured. ++ */ ++ for (int j = 1; j <= 4; j++) { ++ volatile uint64_t *addr64; ++ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr64 = (volatile uint64_t *)(void *)addr; ++ *addr64 = VAL; ++ ++ error = x86_pkru_protect_range(addr, ps[i], j, 0); ++ ATF_REQUIRE(error == 0); ++ switch (j) { ++ case KEY_RW: ++ ATF_REQUIRE(try_write(addr64, VAL)); ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ break; ++ case KEY_RO: ++ ATF_REQUIRE(try_read(addr64, &val)); ++ ATF_REQUIRE(val == VAL); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ case KEY_WO: ++ /* !access implies !modify */ ++ case KEY_NO: ++ ATF_REQUIRE(!try_read(addr64, &val)); ++ ATF_REQUIRE(!try_write(addr64, VAL)); ++ break; ++ default: ++ __unreachable(); ++ } ++ } ++ error = munmap(addr, ps[i]); ++ ATF_CHECK(error == 0); ++ ++ /* ++ * Try mapping a large page in a region partially covered by a ++ * key. ++ * ++ * Rather than detecting the mismatch when the logical mapping ++ * is created, we currently only fail once pmap_enter() is ++ * called from the fault handler. This is not ideal and might ++ * be improved in the future. ++ */ ++ error = x86_pkru_protect_range(addr, ps[i], 0, 0); ++ ATF_REQUIRE(error == 0); ++ error = x86_pkru_protect_range(addr + PAGE_SIZE, ++ ps[i] - PAGE_SIZE, KEY_RW, 0); ++ ATF_REQUIRE(error == 0); ++ ++ addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_FIXED, fd, 0); ++ ATF_REQUIRE(addr1 != MAP_FAILED); ++ ATF_REQUIRE(addr == addr1); ++ ATF_REQUIRE(!try_read((volatile uint64_t *)(void *)addr, &val)); ++ ATF_REQUIRE(!try_write((volatile uint64_t *)(void *)addr, VAL)); ++ } ++} ++#undef KEY_RW ++#undef KEY_RO ++#undef KEY_WO ++#undef KEY_NO ++#endif ++ + ATF_TC_WITHOUT_HEAD(largepage_reopen); + ATF_TC_BODY(largepage_reopen, tc) + { +@@ -1979,6 +2163,9 @@ + ATF_TP_ADD_TC(tp, largepage_mprotect); + ATF_TP_ADD_TC(tp, largepage_minherit); + ATF_TP_ADD_TC(tp, largepage_pipe); ++#ifdef __amd64__ ++ ATF_TP_ADD_TC(tp, largepage_pkru); ++#endif + ATF_TP_ADD_TC(tp, largepage_reopen); + + return (atf_no_error()); diff --git a/website/static/security/patches/SA-26:11/amd64-15.patch.asc b/website/static/security/patches/SA-26:11/amd64-15.patch.asc new file mode 100644 index 0000000000..65ee529c87 --- /dev/null +++ b/website/static/security/patches/SA-26:11/amd64-15.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnnoa0ACgkQbljekB8A +Gu893RAAnR7PfkWxc/HK+biRRz7RkEku19ziW39q7Z3IijNjrTUZ1VkiuCeIIzF1 +Kt6/PPmKQcMwfEAs/CXeeBS6roc85DuSQEhPAURAthJNAwkzKXZyg0C8hU7mAbln +hoPNLFebIyIfpArnhZlWg3/WF5GXtla114xFTNuDnVzdIZmWfUrNmMk73Zuk9rTD +EwfCuyYIbDByDhZ0chwTZHT5fneKDv4cr2wJmOhgEeGvfLnrCzHoNBcNOQo5ESZ1 +/zspLD66DbWIXIGU/yjxJUBsFVFW0xBjLf8Ho7vtBL7ebk91LnhVMJMzDMiZYWoj +bJDtAZOz1hRr8praCf/fPVgL79E3hJYxXHvZBlIozHs/PvGw6zCPQjPbwuGRSbQr +xMYPpCY59GcCZKbgV1+0x/xrEwyheL4EpJIfKeP6rwTGSo0jjDV4VYm5rNQrn2C+ +jmoY6M9Zn+MaBBRyNoLZeo81/A+lfoyNtD0u+81FQHBcHjtzFUDRNCiVatQ6S2N1 +eGPlGXwHYvXu6ukKKuZYPwZwlornYUP0kK5OxjLj3dyUaX6Yb0FxsiZycIQgXKmO +eTB/eZ8gAmBjePYZgSDCYLaKH67yXHjO7OxZVbA9rqtLz0Xzy6NhsE3xH8Bxy558 +FM9Nau2JSXc1UV01EVdqojX1F5svZS0C8sT4Rb+81ugSpdP05ZA= +=9SqI +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:12/dhclient.patch b/website/static/security/patches/SA-26:12/dhclient.patch new file mode 100644 index 0000000000..685dbd8db5 --- /dev/null +++ b/website/static/security/patches/SA-26:12/dhclient.patch @@ -0,0 +1,28 @@ +--- sbin/dhclient/dhclient.c.orig ++++ sbin/dhclient/dhclient.c +@@ -1226,6 +1226,12 @@ + } + memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); + lease->server_name[DHCP_SNAME_LEN]='\0'; ++ if (strchr(lease->server_name, '"') != NULL || ++ strchr(lease->server_name, '\\') != NULL) { ++ warning("dhcpoffer: server name contains invalid characters."); ++ free_client_lease(lease); ++ return (NULL); ++ } + } + + /* Ditto for the filename. */ +@@ -1241,6 +1247,12 @@ + } + memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN); + lease->filename[DHCP_FILE_LEN]='\0'; ++ if (strchr(lease->filename, '"') != NULL || ++ strchr(lease->filename, '\\') != NULL) { ++ warning("dhcpoffer: filename contains invalid characters."); ++ free_client_lease(lease); ++ return (NULL); ++ } + } + return lease; + } diff --git a/website/static/security/patches/SA-26:12/dhclient.patch.asc b/website/static/security/patches/SA-26:12/dhclient.patch.asc new file mode 100644 index 0000000000..bc583398e4 --- /dev/null +++ b/website/static/security/patches/SA-26:12/dhclient.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySSkbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvaFMQAMIYANmaXQyFpQm3qvYC +GNUd5PLa77a9dYDKImZf0yQJaH+/CeiUYh9amwH2YL6HXB7nm+hWPtZonOFoORSH +Ud2C5nwN6MaSRKd9750oOANjrTzxQQ8uOz9pGdbhOcienM7sX/KgrTvhlTS76vvz +ZXgiO3JWP526vNDQDReFfmf6fUHP66UdSQ9jwB21rgwenqJ6Vlkyzy3jts456gsN +/Whoiy843VKkpmTcbY63VpA4zFgBMTLuPIQzgRj9jf61q5/EgUKd/yIj6zJcEzuo +iWibtBqyQyiAmagdPQhp5Dfr+TB+krlNm7b38fbmoxk1Ay8Ppi2eMQXskQ2sE1J2 +kqGCDftu+pSJhma1HEtyDCHsmlbeFfPBPddqDA6uZ26LyRD8DRg+YyrhLgMGZ0k9 +xCcQc3UsQauswSNY6owf1i0uFwcDMI791nF/4buho4ptvC3zAn7kvwCA852vrvqw +rbuEkkUCbh61Li1h4yiOXy6qPRWzIWpRVfZ1+FtBNMylzlp5VHclpdd6ShVeiD/s +ksta7ok4zLZ1oRx19wRgLL79UH1kL6iY6BdITqMEpEjSsMsgAUN1lk97GBeG7k7T +58yhchHqkylEyzkHyU6WqwsmkasUby35s5NUfnZowr4hUJqqiLAGfTslsGWQGEHT +T3lEDazKm9HeEHLwhUeGauuZ +=/8be +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:13/exec.patch b/website/static/security/patches/SA-26:13/exec.patch new file mode 100644 index 0000000000..e6e7457ea4 --- /dev/null +++ b/website/static/security/patches/SA-26:13/exec.patch @@ -0,0 +1,11 @@ +--- sys/kern/kern_exec.c.orig ++++ sys/kern/kern_exec.c +@@ -1650,7 +1650,7 @@ + if (args->stringspace < offset) + return (E2BIG); + memmove(args->begin_argv + extend, args->begin_argv + consume, +- args->endp - args->begin_argv + consume); ++ args->endp - (args->begin_argv + consume)); + if (args->envc > 0) + args->begin_envv += offset; + args->endp += offset; diff --git a/website/static/security/patches/SA-26:13/exec.patch.asc b/website/static/security/patches/SA-26:13/exec.patch.asc new file mode 100644 index 0000000000..b883ac582c --- /dev/null +++ b/website/static/security/patches/SA-26:13/exec.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySSsbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvnE8QAKkLUBigCJQ+vM8p26jJ +bm1Igv0dY4z77RV2CQeSSFhOiOEJFOZHC/oBmMHReFopP5uCD7jSYvR7xeQg4igB +U7R9/1pdtW5tkf0vYAw1RQvxJrfKfEcYkKFvsjQSTokzB0YSUZV/baT6faxlejsu +97hco9YX4gqxPFqEcKh6asoyfnWztm4pRCO+l2kss+nRoVtWevKgCwCUcL+SqhtR +V2Ws8MmgyVWEmRYCgZon9v4d4lF6rZfUoxcXLBHtWz/PcfS686kcOJPq+SPGkkpQ +omj9d66hUhYTJ6zVVtW7Jqo2oY2CFNdsPBNlVzjHscTLZkB7PXKf5HUyli3eaeSN +wrhc6+L886vfROu1KRZsY/EZvxtr0fVeW43yzyfjbdJVcIogvv1HvU9GXSJK6z1M +080caaoMqhtgJL7Xz/c+LJKKQcjAmox53OU1jLLynS5WNIvZGcw7neT+plUm5rQD +PgOmxF0aYNMBZ1T3PSIk9oD2aoTszbZMUPLOS92LIxBMVFTdwI5A4jwIMUDtqVd0 +b7Pp2Uyc4O6Qss5fjEwIy79EipAGTg5iBA1wXj/NpkH7zA+5bZNrni0ulgD6y9lY +H9BFmNV1Mg9C1g3kK5SnOoQmwg9rNumTrCtKvGLNJGGe0vmJXyVz6G+88sNWCLIK +lvWj8cYJ1CQONZcNB6YQg0f/ +=VO73 +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:14/pf-135.patch b/website/static/security/patches/SA-26:14/pf-135.patch new file mode 100644 index 0000000000..ca5c96cce1 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-135.patch @@ -0,0 +1,165 @@ +--- sys/netpfil/pf/pf.c.orig ++++ sys/netpfil/pf/pf.c +@@ -5925,7 +5925,7 @@ + + static int + pf_multihome_scan(struct mbuf *m, int start, int len, struct pf_pdesc *pd, +- struct pfi_kkif *kif, int op) ++ struct pfi_kkif *kif, int op, bool asconf) + { + int off = 0; + struct pf_sctp_multihome_job *job; +@@ -6019,13 +6019,16 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_ADD_IP_ADDRESS); ++ SCTP_ADD_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6034,12 +6037,15 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_DEL_IP_ADDRESS); ++ SCTP_DEL_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6061,7 +6067,8 @@ + start += sizeof(struct sctp_init_chunk); + len -= sizeof(struct sctp_init_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +@@ -6071,7 +6078,8 @@ + start += sizeof(struct sctp_asconf_chunk); + len -= sizeof(struct sctp_asconf_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +--- tests/sys/netpfil/pf/sctp.py.orig ++++ tests/sys/netpfil/pf/sctp.py +@@ -426,6 +426,96 @@ + assert re.search(r"all sctp 192.0.2.4:.*192.0.2.3:1234", states) + assert re.search(r"all sctp 192.0.2.4:.*192.0.2.2:1234", states) + ++class TestSCTP_SRV(VnetTestTemplate): ++ REQUIRED_MODULES = ["sctp", "pf"] ++ TOPOLOGY = { ++ "vnet1": {"ifaces": ["if1"]}, ++ "vnet2": {"ifaces": ["if1"]}, ++ "if1": {"prefixes4": [("192.0.2.1/24", "192.0.2.2/24")]}, ++ } ++ ++ def vnet2_handler(self, vnet): ++ ToolsHelper.print_output("/sbin/pfctl -e") ++ ToolsHelper.pf_rules([ ++ "set state-policy if-bound", ++ "pass inet proto sctp", ++ "pass on lo"]) ++ ++ # Start an SCTP server process, pipe the ppid + data back to the other vnet? ++ srv = SCTPServer(socket.AF_INET, port=1234) ++ while True: ++ srv.accept(vnet) ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_initiate_tag_check(self): ++ # Ensure we don't send ABORTs in response to the other end's INIT_ACK ++ # That'd interfere with our test. ++ ToolsHelper.print_output("/sbin/sysctl net.inet.sctp.blackhole=2") ++ ++ import scapy.all as sp ++ ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send another INIT with the same initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send an INIT with a different initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=42, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 42 ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_too_many_add_ip(self): ++ import scapy.all as sp ++ DEPTH=90 ++ params=[] ++ for i in range(0, DEPTH): ++ ch = sp.SCTPChunkParamAddIPAddr(len=(DEPTH - i) * 8) ++ params.append(ch) ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=4321, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500, ++ params=params) ++ packet.show() ++ sp.hexdump(packet) ++ print("len %d" % len(packet)) ++ ++ r = sp.sr1(packet, timeout=3) ++ # We should not get a reply to this ++ if r: ++ r.show() ++ assert not r ++ + class TestSCTPv6(VnetTestTemplate): + REQUIRED_MODULES = ["sctp", "pf"] + TOPOLOGY = { diff --git a/website/static/security/patches/SA-26:14/pf-135.patch.asc b/website/static/security/patches/SA-26:14/pf-135.patch.asc new file mode 100644 index 0000000000..b61113af83 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-135.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySS4bFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvRrQP/0RL9f1xsHaz6snxUSJ7 +shCQY37JVSW9AfioEkAiGz6JWq0gZM6k+BzwaZYkt77ihqxCNtWtAGlHiP/tXYeQ +rf5VceESLHxJO6kzRkurY7EvDoxYIOYa6R7+q9ReZAubucAbGsLQ8Ht9wc8bFn5c +baXTvPUPJ81g/cRMosz2PCn8FIygPRBiN2Tamymiiz79+Pa7bJwtWjC35S5z4kMI +NPbh3sTdfSH48Z745ZTFlnNNGfoV0NLfRYEJ4kvH8tzTQK3q0ZDKRzFM1mFmw9dg +m83pbiJzEN26yF2xy8tAWxnb6ag0DjcV7itkkV2eCpdCijvvxIMDhiH4Ez7soSvb +lFRCHAcl4nXmUMJUHLqj/C5eugTd2V+bji5c4di9gpgUol8ui8R23TrXd41r+x/8 +lsZf/CdVfFGrTQo8Aq6Q/0TUXUZdnLduyRMtWAKW/9Ux9st5rtPaj3jlFkA0kddm +2K22hzl122cD9JS2G2XZbOBI88I0rvHZtL25TRZ7PLDD+41LYKDt9KWPuZVG/Xyv +fTizW+QgorTx6C/yqGgsMSIz94pe04fw3Ayj0zwB2neRYL38P1ZpUCNOk11RVAg0 +pp+TmZjhzHAjaeCrdQ/8GZfryNyOjT3HyPXrPvelT1icn1gkrLgjRWqHyVLHYLVe +OPaBXvbJCSqLUMQZDgcRLY/e +=i3Tv +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:14/pf-143.patch b/website/static/security/patches/SA-26:14/pf-143.patch new file mode 100644 index 0000000000..866d0abc6d --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-143.patch @@ -0,0 +1,165 @@ +--- sys/netpfil/pf/pf.c.orig ++++ sys/netpfil/pf/pf.c +@@ -6581,7 +6581,7 @@ + + static int + pf_multihome_scan(struct mbuf *m, int start, int len, struct pf_pdesc *pd, +- struct pfi_kkif *kif, int op) ++ struct pfi_kkif *kif, int op, bool asconf) + { + int off = 0; + struct pf_sctp_multihome_job *job; +@@ -6684,13 +6684,16 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_ADD_IP_ADDRESS); ++ SCTP_ADD_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6699,12 +6702,15 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_DEL_IP_ADDRESS); ++ SCTP_DEL_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6726,7 +6732,8 @@ + start += sizeof(struct sctp_init_chunk); + len -= sizeof(struct sctp_init_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +@@ -6736,7 +6743,8 @@ + start += sizeof(struct sctp_asconf_chunk); + len -= sizeof(struct sctp_asconf_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +--- tests/sys/netpfil/pf/sctp.py.orig ++++ tests/sys/netpfil/pf/sctp.py +@@ -502,6 +502,96 @@ + assert re.search(r"epair.*sctp 192.0.2.1:.*192.0.2.3:1234", states) + assert re.search(r"epair.*sctp 192.0.2.1:.*192.0.2.2:1234", states) + ++class TestSCTP_SRV(VnetTestTemplate): ++ REQUIRED_MODULES = ["sctp", "pf"] ++ TOPOLOGY = { ++ "vnet1": {"ifaces": ["if1"]}, ++ "vnet2": {"ifaces": ["if1"]}, ++ "if1": {"prefixes4": [("192.0.2.1/24", "192.0.2.2/24")]}, ++ } ++ ++ def vnet2_handler(self, vnet): ++ ToolsHelper.print_output("/sbin/pfctl -e") ++ ToolsHelper.pf_rules([ ++ "set state-policy if-bound", ++ "pass inet proto sctp", ++ "pass on lo"]) ++ ++ # Start an SCTP server process, pipe the ppid + data back to the other vnet? ++ srv = SCTPServer(socket.AF_INET, port=1234) ++ while True: ++ srv.accept(vnet) ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_initiate_tag_check(self): ++ # Ensure we don't send ABORTs in response to the other end's INIT_ACK ++ # That'd interfere with our test. ++ ToolsHelper.print_output("/sbin/sysctl net.inet.sctp.blackhole=2") ++ ++ import scapy.all as sp ++ ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send another INIT with the same initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send an INIT with a different initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=42, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 42 ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_too_many_add_ip(self): ++ import scapy.all as sp ++ DEPTH=90 ++ params=[] ++ for i in range(0, DEPTH): ++ ch = sp.SCTPChunkParamAddIPAddr(len=(DEPTH - i) * 8) ++ params.append(ch) ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=4321, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500, ++ params=params) ++ packet.show() ++ sp.hexdump(packet) ++ print("len %d" % len(packet)) ++ ++ r = sp.sr1(packet, timeout=3) ++ # We should not get a reply to this ++ if r: ++ r.show() ++ assert not r ++ + class TestSCTPv6(VnetTestTemplate): + REQUIRED_MODULES = ["sctp", "pf"] + TOPOLOGY = { diff --git a/website/static/security/patches/SA-26:14/pf-143.patch.asc b/website/static/security/patches/SA-26:14/pf-143.patch.asc new file mode 100644 index 0000000000..81201d7968 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-143.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySS8bFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrv7FkP/iEomxbELiAbeTx9askL +VytDSUjb5lJAaclJ7r9hqvSJJ1ne5p1++KvFDMcrUHv/kAS5SfnPK55QpxMYJbW2 +CR45UgGGzQNAToptsRTbZUCmWDe9/vFkSGk3yoYL6JPGAJc7fbvewzuzcE8yCeDO +qHpjoCNGx0MqXciGJSUlQ/ztxXJST3KHQ6qg7OaOuhSbeJv39vSgEukQWo83TE6t +2odt2iL2sysWufsMECPeom8L5wvXa5BJikGnjMO5CNcGSwy/T+0eTkz7EkJHJAMa +wkezIjDobfyt2DY4/s3OWDA7RnOE+1bhsyeTUtrruI5Gz3hU04WlgBDrCd9i5TmG +E6qfaOfXPeLdipScggTUy+5nKt89eqn40Ay0xqu3FnvEK2VcfiHNUam7cB7g5qOh +ymSctW3nOjgTZA600Xgb+0iHNMQC0nGKzQUyiPIrJSQ66Iic2zkP307s+d5Em6KB +p+lINIcq66it24SA6pxcqhTEks1ekpxJ+gcAEUbHlwOly9EBvopFxLW3o7U+wKVz ++WyEShMsnskPPZA/2NN5FKedP3NcLShMb3axVUxxe90w4QFj1G0TvNZZubi1374c +2LUCIg2GX5HAyScapJd7Bex5qpLjZU8Ll6cYV7bgRAf8v7zPXP8V+sNL7KlQ0WR8 +I5mSyKAVWDX/RfaZ0fiHDjUs +=krWa +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:14/pf-144.patch b/website/static/security/patches/SA-26:14/pf-144.patch new file mode 100644 index 0000000000..469fce184d --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-144.patch @@ -0,0 +1,98 @@ +--- sys/netpfil/pf/pf.c.orig ++++ sys/netpfil/pf/pf.c +@@ -6597,7 +6597,7 @@ + + static int + pf_multihome_scan(struct mbuf *m, int start, int len, struct pf_pdesc *pd, +- struct pfi_kkif *kif, int op) ++ struct pfi_kkif *kif, int op, bool asconf) + { + int off = 0; + struct pf_sctp_multihome_job *job; +@@ -6700,13 +6700,16 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_ADD_IP_ADDRESS); ++ SCTP_ADD_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6715,12 +6718,15 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + ret = pf_multihome_scan(m, start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, kif, +- SCTP_DEL_IP_ADDRESS); ++ SCTP_DEL_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -6742,7 +6748,8 @@ + start += sizeof(struct sctp_init_chunk); + len -= sizeof(struct sctp_init_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +@@ -6752,7 +6759,8 @@ + start += sizeof(struct sctp_asconf_chunk); + len -= sizeof(struct sctp_asconf_chunk); + +- return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(m, start, len, pd, kif, SCTP_ADD_IP_ADDRESS, ++ false)); + } + + int +--- tests/sys/netpfil/pf/sctp.py.orig ++++ tests/sys/netpfil/pf/sctp.py +@@ -597,6 +597,29 @@ + assert r.getlayer(sp.SCTPChunkInitAck) + assert r.getlayer(sp.SCTP).tag == 42 + ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_too_many_add_ip(self): ++ import scapy.all as sp ++ DEPTH=90 ++ params=[] ++ for i in range(0, DEPTH): ++ ch = sp.SCTPChunkParamAddIPAddr(len=(DEPTH - i) * 8) ++ params.append(ch) ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=4321, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500, ++ params=params) ++ packet.show() ++ sp.hexdump(packet) ++ print("len %d" % len(packet)) ++ ++ r = sp.sr1(packet, timeout=3) ++ # We should not get a reply to this ++ if r: ++ r.show() ++ assert not r ++ + class TestSCTPv6(VnetTestTemplate): + REQUIRED_MODULES = ["sctp", "pf"] + TOPOLOGY = { diff --git a/website/static/security/patches/SA-26:14/pf-144.patch.asc b/website/static/security/patches/SA-26:14/pf-144.patch.asc new file mode 100644 index 0000000000..720bbfabc6 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-144.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTAbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrveZgP/0akphviG2lscL9kkOeZ +0DlTlrttI84an5OV8h0tR0pVTIHUUxLoTpp71w0TRzvE5r7qvx6AJJbpJ34daahK +KVhNWat+KOzp1IHcYCrxkBVpLtpZvzMjUqLL7gcaZ5mmw+jnQzp+wLxxlNuPIWq7 +BJC6bWKJ5CS9uUbNa4RTwZRk0gtb1TLFFS7/sE8F1x2WJCDQ+w4nJSzbFdoJEatD +m08qFdetspNrC65yQiRoxgJFwbrfoL/BjjhEymd2gJLdQmXVvcEgrBm2o/7SGqxR +a8D3HacJfAyZ2umW0WC/hpglk7XHhJSaH6xQSgOh5rRhfAVJU4YoNBhRfViv4pk/ +1ce48JYXV8uvEj8fekrtgXoOUM3OUzhNsYJ0M8k1g8frTH1amF2hBHvnXPVVfQ+U +6JyWrUDKwPS4c1aTD7nJwk9Nxc9/bCu4UnfozTsqrhOAMp+8H1NiiYU/X4CNbs0W +v1xMnv+XnhuD8JMh+4//iQ9PXdag6C2+J8IdVXbMWYV16gSZxQHXEbkiJ7Y/0Zu8 +0KM4JjFdbi7TuCdJoi3Sx9DNgUtUUO3A+n3GA44LIco1RXywTggnWxDBLWk8Xs5+ +BBDICpl+sEM8/xFDRZGL0oEbmYr4zeoPC9PGoXWrbQcUX0SWNNq9looS1Nw1g08M +u695Ky2K2SlRd83Eo1HzzYHO +=jN0s +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:14/pf-150.patch b/website/static/security/patches/SA-26:14/pf-150.patch new file mode 100644 index 0000000000..fc6d251c87 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-150.patch @@ -0,0 +1,163 @@ +--- sys/netpfil/pf/pf.c.orig ++++ sys/netpfil/pf/pf.c +@@ -7664,7 +7664,7 @@ + } + + static int +-pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op) ++pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op, bool asconf) + { + int off = 0; + struct pf_sctp_multihome_job *job; +@@ -7769,13 +7769,16 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(pd->m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + + ret = pf_multihome_scan(start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, +- SCTP_ADD_IP_ADDRESS); ++ SCTP_ADD_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -7784,12 +7787,15 @@ + int ret; + struct sctp_asconf_paramhdr ah; + ++ if (asconf) ++ return (PF_DROP); ++ + if (!pf_pull_hdr(pd->m, start + off, &ah, sizeof(ah), + NULL, NULL, pd->af)) + return (PF_DROP); + ret = pf_multihome_scan(start + off + sizeof(ah), + ntohs(ah.ph.param_length) - sizeof(ah), pd, +- SCTP_DEL_IP_ADDRESS); ++ SCTP_DEL_IP_ADDRESS, true); + if (ret != PF_PASS) + return (ret); + break; +@@ -7810,7 +7816,7 @@ + start += sizeof(struct sctp_init_chunk); + len -= sizeof(struct sctp_init_chunk); + +- return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS, false)); + } + + int +@@ -7819,7 +7825,7 @@ + start += sizeof(struct sctp_asconf_chunk); + len -= sizeof(struct sctp_asconf_chunk); + +- return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS)); ++ return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS, false)); + } + + int +--- tests/sys/netpfil/pf/sctp.py.orig ++++ tests/sys/netpfil/pf/sctp.py +@@ -551,6 +551,96 @@ + assert re.search(r"epair.*sctp 192.0.2.1:.*192.0.2.3:1234", states) + assert re.search(r"epair.*sctp 192.0.2.1:.*192.0.2.2:1234", states) + ++class TestSCTP_SRV(VnetTestTemplate): ++ REQUIRED_MODULES = ["sctp", "pf"] ++ TOPOLOGY = { ++ "vnet1": {"ifaces": ["if1"]}, ++ "vnet2": {"ifaces": ["if1"]}, ++ "if1": {"prefixes4": [("192.0.2.1/24", "192.0.2.2/24")]}, ++ } ++ ++ def vnet2_handler(self, vnet): ++ ToolsHelper.print_output("/sbin/pfctl -e") ++ ToolsHelper.pf_rules([ ++ "set state-policy if-bound", ++ "pass inet proto sctp", ++ "pass on lo"]) ++ ++ # Start an SCTP server process, pipe the ppid + data back to the other vnet? ++ srv = SCTPServer(socket.AF_INET, port=1234) ++ while True: ++ srv.accept(vnet) ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_initiate_tag_check(self): ++ # Ensure we don't send ABORTs in response to the other end's INIT_ACK ++ # That'd interfere with our test. ++ ToolsHelper.print_output("/sbin/sysctl net.inet.sctp.blackhole=2") ++ ++ import scapy.all as sp ++ ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send another INIT with the same initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 1 ++ ++ # Send an INIT with a different initiate tag, expect another init ack ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=1234, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=42, n_in_streams=1, n_out_streams=1, a_rwnd=1500) ++ packet.show() ++ ++ r = sp.sr1(packet, timeout=3) ++ assert r ++ r.show() ++ assert r.getlayer(sp.SCTP) ++ assert r.getlayer(sp.SCTPChunkInitAck) ++ assert r.getlayer(sp.SCTP).tag == 42 ++ ++ @pytest.mark.require_user("root") ++ @pytest.mark.require_progs(["scapy"]) ++ def test_too_many_add_ip(self): ++ import scapy.all as sp ++ DEPTH=90 ++ params=[] ++ for i in range(0, DEPTH): ++ ch = sp.SCTPChunkParamAddIPAddr(len=(DEPTH - i) * 8) ++ params.append(ch) ++ packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ ++ / sp.SCTP(sport=4321, dport=1234) \ ++ / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500, ++ params=params) ++ packet.show() ++ sp.hexdump(packet) ++ print("len %d" % len(packet)) ++ ++ r = sp.sr1(packet, timeout=3) ++ # We should not get a reply to this ++ if r: ++ r.show() ++ assert not r ++ + class TestSCTPv6(VnetTestTemplate): + REQUIRED_MODULES = ["sctp", "pf"] + TOPOLOGY = { diff --git a/website/static/security/patches/SA-26:14/pf-150.patch.asc b/website/static/security/patches/SA-26:14/pf-150.patch.asc new file mode 100644 index 0000000000..405e39adf0 --- /dev/null +++ b/website/static/security/patches/SA-26:14/pf-150.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTIbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvTCEP/i2QxOe9xSXmgh7Af5z+ +uyT9i6jcCmsE0lesUjuQamIiOd+dxBgGpfF95eFpmKFLj5r9RDr3whojzxnr1Uph +NrcINE06DR7HmpVDKN78ltnohyALdF/kaWCim7etlHFNW1xHu/MIAD+vYpYcGnge +mHa/c72G+/TtcNMF6x2HXcwQb0zRs4uNqHFWhz/SDcw8KUJL/aP9Ouusu5Rxxszz +3r8JQ1WEkbleKeQ/7IUpqV97Dsn2GWGQbdb+KT8HMPhGB+KMPQdMXLbA0CKBeVO2 +uLoH2MmyScZ992xShzGjoxUJ98yzecpJ0dAyhijhoC2QZiKHRRAgExq9z9rdi8JE +TiRPUmP8I/o6tX6zcxGUImxUpREFAjlV/PjsvUUto0AT4Xj781aeaxuQS/j5Jr9c +5R6E0/siCAlPaxcax84ToDpkkhcHO66Nb7ZrZRoZo+zMbVqqlQw9ZVvA10tZU+Sh +r/umUGcp8ucyMcxtbYINuGo2MGn/W5+oRmOYyyWT860ZkyleFDGNSrHDoQaHo4y1 +AUJIQfbWenGVUau86Nd6gso5FFRbvWVaLh/KAfcaJPaWGtJSeolKoQze3Nu/kXlP +c/YIphCU1k727n0bn2lzH7TGSoaHJjZK608jIhbgsNcmP19ySmIAvsQexmbGWXIv +u3setGkJuR2Hglhingi43COl +=CoBq +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:15/dhclient.patch b/website/static/security/patches/SA-26:15/dhclient.patch new file mode 100644 index 0000000000..8fd33f1d86 --- /dev/null +++ b/website/static/security/patches/SA-26:15/dhclient.patch @@ -0,0 +1,13 @@ +--- sbin/dhclient/dhclient.c.orig ++++ sbin/dhclient/dhclient.c +@@ -2438,8 +2438,8 @@ + char **newscriptEnv; + int newscriptEnvsize = client->scriptEnvsize + 50; + +- newscriptEnv = realloc(client->scriptEnv, +- newscriptEnvsize); ++ newscriptEnv = reallocarray(client->scriptEnv, ++ newscriptEnvsize, sizeof(char *)); + if (newscriptEnv == NULL) { + free(client->scriptEnv); + client->scriptEnv = NULL; diff --git a/website/static/security/patches/SA-26:15/dhclient.patch.asc b/website/static/security/patches/SA-26:15/dhclient.patch.asc new file mode 100644 index 0000000000..3eb0cd2be6 --- /dev/null +++ b/website/static/security/patches/SA-26:15/dhclient.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTQbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvCBsP/3TEOnARDBrSuHaAEPeS +5H8Jmuxlu7bw9jYlvOUOf5VxEKAFtegEISGabjRgwdOGLneiUGYIpWytYSF0XCoJ +5HQIKmhq6HSPWAStE91pJEcn1QbmXuOeVwUmkwahVHrtvJ3IP6X+VsqbRSdBn6Eu +jLKasjYQGD161es38q3JFUN/dHwCkb653cYYkGOHI9LrbfAh9LxveGF8EEDQehz4 +qmY8b0KbfDxo8wIHKiBRuKbjnBbMvTJhCafYKQkSEwSvATiU8mXNTrnVFc25OMpm +0tPwCicFbli8lzuMvoc7u/6yAKLR6YFUjn6gXo7wSXfp1J0xl2KyOmFnKPCVUFHr ++WQvCwLHkvUoFNmAaQMAGgrfVNfyCd5tiA0P+CSeLudBmEy1WGleFFtLyIfFNmCF +kQNn0BRs5zEgBbCpymlIhZg5BwW8zVKAfc6oTqI0M36mADfvFeReY0ySQxdZamAP +1vt/Ml6XiS5V1tsdWnLuUcetuUAYBFm4rPU7Q8NrhRj7+jikaq704Dc429HY6Xmd +KlWF9QpEF36G+Yy0FPJCW6nI9HgAX1EC0oMJG4n+lsh6AEUt0D+GLzZc+06Umiuw +3PXKPps6UP781VR9jazsBbEAYi08kvpZ4dScAyvpuMOCipmgDmE1l6ma9zKT+jyd +xe8EBRPy1MqtjgGdcb5jbEXq +=eEnh +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:16/libnv.patch b/website/static/security/patches/SA-26:16/libnv.patch new file mode 100644 index 0000000000..5b549f693c --- /dev/null +++ b/website/static/security/patches/SA-26:16/libnv.patch @@ -0,0 +1,34 @@ +--- lib/libnv/msgio.c.orig ++++ lib/libnv/msgio.c +@@ -32,10 +32,10 @@ + + #include <sys/param.h> + #include <sys/socket.h> +-#include <sys/select.h> + + #include <errno.h> + #include <fcntl.h> ++#include <poll.h> + #include <stdbool.h> + #include <stdint.h> + #include <stdlib.h> +@@ -86,14 +86,14 @@ + static void + fd_wait(int fd, bool doread) + { +- fd_set fds; ++ struct pollfd pfd; + + PJDLOG_ASSERT(fd >= 0); + +- FD_ZERO(&fds); +- FD_SET(fd, &fds); +- (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, +- NULL, NULL); ++ pfd.fd = fd; ++ pfd.events = doread ? POLLIN : POLLOUT; ++ pfd.revents = 0; ++ (void)poll(&pfd, 1, -1); + } + + static int diff --git a/website/static/security/patches/SA-26:16/libnv.patch.asc b/website/static/security/patches/SA-26:16/libnv.patch.asc new file mode 100644 index 0000000000..0437dcc866 --- /dev/null +++ b/website/static/security/patches/SA-26:16/libnv.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTcbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvT/YP/jo1mhRgCckLHppmcOEh +tcI3q45vtzARNaPWSvAyJ7DajTgv6pCVTqzBWw4sY61/VU6wFNscpsu/+IvrlFjw +dwgyxtZFU5jxwsxtVyY4p8YwZTInyEh8kNacvh7vbBB5ILHc24pVEOEXP+8VCq37 +DBfOJ/FPB2vMLOWISgEPZtH8ZgXN5Id/LtfdJVMh26Ls+SSHcWlzFgI+9I29m+9J +JcsQTpXGjjXpzltW0QJ+KZzhcuh4GJ6e5cNtk6wArSCVPkDkfW0XE8HIgYmb4JAz +KWXvpD86xOPMZ8qFbtQMOELO4skI6bEnHrQbMR/t8eXERCT31s6IL6iPST7hLZfY +9mnXMpYe4nhgNfZlDbW4wUSP1bQft2zVpUxu/8elOEDCgUhF871zdpm1AC99kbau +AezJe9S6n93qttPEFjv6KPT3s+HPtIHxXtF2J9A2x690x+unpDQO6ZxI0pVZ+290 +wSJ4gJk7g/CUID2FSDPbh5fvM5lbT9d7kdgYn9F99SdchWC57xZfnBIh1VnOySQJ +Jiv7n804Ya+MNA1skiCiOPjHwLtsdeD6KDjNi/kOK4VVVm6YzFhQRGhwS2Q58S51 +Ah8t4H7PmDBXISevSTviBGxsnuU5ue2Kowoel4aW5dP2vZaRTAGkeAkU4Ar5b8FL +W5b5K9lDK+uenRxd+Tsk5NZV +=1JCa +-----END PGP SIGNATURE----- diff --git a/website/static/security/patches/SA-26:17/libnv.patch b/website/static/security/patches/SA-26:17/libnv.patch new file mode 100644 index 0000000000..6d3319998c --- /dev/null +++ b/website/static/security/patches/SA-26:17/libnv.patch @@ -0,0 +1,25 @@ +--- sys/contrib/libnv/nvlist.c.orig ++++ sys/contrib/libnv/nvlist.c +@@ -1027,10 +1027,6 @@ + nvlist_check_header(struct nvlist_header *nvlhdrp) + { + +- if (nvlhdrp->nvlh_size > SIZE_MAX - sizeof(*nvlhdrp)) { +- ERRNO_SET(EINVAL); +- return (false); +- } + if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { + ERRNO_SET(EINVAL); + return (false); +@@ -1050,6 +1046,11 @@ + nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); + } + #endif ++ if (nvlhdrp->nvlh_size > SIZE_MAX - sizeof(*nvlhdrp)) { ++ ERRNO_SET(EINVAL); ++ return (false); ++ } ++ + return (true); + } + diff --git a/website/static/security/patches/SA-26:17/libnv.patch.asc b/website/static/security/patches/SA-26:17/libnv.patch.asc new file mode 100644 index 0000000000..1504f46f09 --- /dev/null +++ b/website/static/security/patches/SA-26:17/libnv.patch.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJPBAABCgA5FiEEthUnfoEIffdcgYM7bljekB8AGu8FAmnySTkbFIAAAAAABAAO +bWFudTIsMi41KzEuMTIsMCwzAAoJEG5Y3pAfABrvmnkQAOWbqIvH2qArIUinHfHj +wFM+jT5a9RVIpYSivl5MTOgB9Uiy4Ivhv4QE4hnX9hEoojJ9pHrUf6WGXnS/19VV +UVDKDw6IID1ABvCSb86cfjbHizNqTmMmLF6uYBC94MBur45GnVTFavm1Ua1avziF +dSUesdm9/bsupMSVvhUDIry5fmi3pO6bGJEouJ3G8/NXUY5ouvouiyNlMHzSdRiy +2NS9wXqmqNZezm1kh/eYv6/95Yke1O2+LcnYfl0aY9EPcbw7MNxgeSUUw04YmnF1 +2dlXPQivOIijEVZWfHNKUcqzarttns2ejPtB9MnohsoIT07qCSTuq8MXHVAuvs0J +BZ8EKABKhNMRqedBbptQy3s03KYH9ThgUSTr9H1dyBpNWwlvMdtcE1aQfcugVG+9 +/iVt1fOhw7m+W37/UKjMDq7raOKznflcFKuO0Pubqk6eqiEHRCas3oP0tHjQCd+B +bxBrRIjsOodR7nnm7HOhbGleOdddbINS+PEAVLISB95CBDWefHz9+C5y5SlSmdjQ +IEPuEJKfwjYjrjYHuZ9i/YK9Vqpyc5yeRb8qefXJcReGm0tKwFX6J7FSSW8dwqPK +g504ivZUxHaQV9fUgRTZp96i4EwRe9jsVdDbfoLJGnwcLhf7Ip+2jbHemSrm0z2Y +tMLW/sZ9EkWquaXK/iClB/pM +=71Gx +-----END PGP SIGNATURE----- |
