aboutsummaryrefslogtreecommitdiff
path: root/website/static/security
diff options
context:
space:
mode:
Diffstat (limited to 'website/static/security')
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:01.devinfo.asc127
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:02.arm64.asc137
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:03.vm.asc144
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:04.arm64.asc137
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:05.vm.asc158
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:06.timerfd.asc140
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:07.pkgbase.asc113
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:08.pf.asc139
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:09.tzdata.asc179
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:10.amd64.asc155
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:11.dhclient.asc156
-rw-r--r--website/static/security/advisories/FreeBSD-EN-26:12.freebsd-update.asc178
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:01.openssl.asc203
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:02.jail.asc150
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:03.blocklistd.asc164
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:04.jail.asc165
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:05.route.asc161
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:06.tcp.asc180
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:07.nvmf.asc140
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc163
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:09.pf.asc168
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:10.tty.asc165
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:11.amd64.asc163
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:12.dhclient.asc155
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:13.exec.asc150
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:14.pf.asc168
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:15.dhclient.asc159
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:16.libnv.asc152
-rw-r--r--website/static/security/advisories/FreeBSD-SA-26:17.libnv.asc156
-rw-r--r--website/static/security/advisory-template.txt77
-rw-r--r--website/static/security/errata-template.txt75
-rw-r--r--website/static/security/patches/EN-26:01/devinfo.patch477
-rw-r--r--website/static/security/patches/EN-26:01/devinfo.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:02/arm64-14.patch66
-rw-r--r--website/static/security/patches/EN-26:02/arm64-14.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:02/arm64-15.patch66
-rw-r--r--website/static/security/patches/EN-26:02/arm64-15.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:03/vm-13.patch62
-rw-r--r--website/static/security/patches/EN-26:03/vm-13.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:03/vm-14.patch62
-rw-r--r--website/static/security/patches/EN-26:03/vm-14.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:03/vm-15.patch62
-rw-r--r--website/static/security/patches/EN-26:03/vm-15.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:04/arm64.patch22
-rw-r--r--website/static/security/patches/EN-26:04/arm64.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:05/vm-13.patch37
-rw-r--r--website/static/security/patches/EN-26:05/vm-13.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:05/vm-14.patch37
-rw-r--r--website/static/security/patches/EN-26:05/vm-14.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:05/vm-15.patch37
-rw-r--r--website/static/security/patches/EN-26:05/vm-15.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:06/timerfd.patch39
-rw-r--r--website/static/security/patches/EN-26:06/timerfd.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:07/pkgbase.patch22
-rw-r--r--website/static/security/patches/EN-26:07/pkgbase.patch.asc16
-rw-r--r--website/static/security/patches/EN-26:08/pf.patch69
-rw-r--r--website/static/security/patches/EN-26:08/pf.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:09/tzdata-2026b-144.patch681
-rw-r--r--website/static/security/patches/EN-26:09/tzdata-2026b-144.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:09/tzdata-2026b.patch3015
-rw-r--r--website/static/security/patches/EN-26:09/tzdata-2026b.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:10/amd64.patch34
-rw-r--r--website/static/security/patches/EN-26:10/amd64.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:11/dhclient.patch112
-rw-r--r--website/static/security/patches/EN-26:11/dhclient.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:12/ensa-135.patch56
-rw-r--r--website/static/security/patches/EN-26:12/ensa-135.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:12/ensa-143.patch487
-rw-r--r--website/static/security/patches/EN-26:12/ensa-143.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:12/ensa-144.patch487
-rw-r--r--website/static/security/patches/EN-26:12/ensa-144.patch.asc17
-rw-r--r--website/static/security/patches/EN-26:12/ensa-150.patch166
-rw-r--r--website/static/security/patches/EN-26:12/ensa-150.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:01/openssl-13.patch194
-rw-r--r--website/static/security/patches/SA-26:01/openssl-13.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:01/openssl-14.patch251
-rw-r--r--website/static/security/patches/SA-26:01/openssl-14.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:01/openssl-15.patch550
-rw-r--r--website/static/security/patches/SA-26:01/openssl-15.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:02/jail-13.patch550
-rw-r--r--website/static/security/patches/SA-26:02/jail-13.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:02/jail-14.patch498
-rw-r--r--website/static/security/patches/SA-26:02/jail-14.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:03/blocklistd.patch173
-rw-r--r--website/static/security/patches/SA-26:03/blocklistd.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:04/jail-13.patch1132
-rw-r--r--website/static/security/patches/SA-26:04/jail-13.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:04/jail-14.patch1173
-rw-r--r--website/static/security/patches/SA-26:04/jail-14.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:05/route.patch13
-rw-r--r--website/static/security/patches/SA-26:05/route.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:06/tcp.patch11
-rw-r--r--website/static/security/patches/SA-26:06/tcp.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:07/nvmf.patch12
-rw-r--r--website/static/security/patches/SA-26:07/nvmf.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:08/rpcsec_gss.patch51
-rw-r--r--website/static/security/patches/SA-26:08/rpcsec_gss.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:09/pf-14.patch212
-rw-r--r--website/static/security/patches/SA-26:09/pf-14.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:09/pf-15.patch224
-rw-r--r--website/static/security/patches/SA-26:09/pf-15.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:10/tty-13.patch108
-rw-r--r--website/static/security/patches/SA-26:10/tty-13.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:10/tty-14.3.patch108
-rw-r--r--website/static/security/patches/SA-26:10/tty-14.3.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:10/tty-14.4.patch108
-rw-r--r--website/static/security/patches/SA-26:10/tty-14.4.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:10/tty-15.patch108
-rw-r--r--website/static/security/patches/SA-26:10/tty-15.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:11/amd64-13.patch397
-rw-r--r--website/static/security/patches/SA-26:11/amd64-13.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:11/amd64-14.patch397
-rw-r--r--website/static/security/patches/SA-26:11/amd64-14.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:11/amd64-15.patch397
-rw-r--r--website/static/security/patches/SA-26:11/amd64-15.patch.asc16
-rw-r--r--website/static/security/patches/SA-26:12/dhclient.patch28
-rw-r--r--website/static/security/patches/SA-26:12/dhclient.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:13/exec.patch11
-rw-r--r--website/static/security/patches/SA-26:13/exec.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:14/pf-135.patch165
-rw-r--r--website/static/security/patches/SA-26:14/pf-135.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:14/pf-143.patch165
-rw-r--r--website/static/security/patches/SA-26:14/pf-143.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:14/pf-144.patch98
-rw-r--r--website/static/security/patches/SA-26:14/pf-144.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:14/pf-150.patch163
-rw-r--r--website/static/security/patches/SA-26:14/pf-150.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:15/dhclient.patch13
-rw-r--r--website/static/security/patches/SA-26:15/dhclient.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:16/libnv.patch34
-rw-r--r--website/static/security/patches/SA-26:16/libnv.patch.asc17
-rw-r--r--website/static/security/patches/SA-26:17/libnv.patch25
-rw-r--r--website/static/security/patches/SA-26:17/libnv.patch.asc17
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(&copy, " ")) != 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&rarr;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&deg;
++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>&lt;+08&gt;-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&ndash;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&ndash;1930,
++ BMT/BST for Bermuda 1890–1930,
+ CMT/BST for Calamarca Mean Time and Bolivian Summer Time
+- 1890&ndash;1932,
++ 1890–1932,
+ DMT/IST for Dublin/Dunsink Mean Time and Irish Summer Time
+- 1880&ndash;1916,
+- MMT/MST/MDST for Moscow 1880&ndash;1919, and
+- RMT/LST for Riga Mean Time and Latvian Summer time 1880&ndash;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&ndash;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&amp;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>
+- &minus;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&ndash;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>&lt;+09&gt;</code>';
++ may also be quoted in angle brackets, like <code>&lt;+09&gt;</code>;
+ this allows "<code>+</code>" and "<code>-</code>" in the names.
+ </dd>
+ <dt><var>offset</var></dt><dd>
+ is of the form
+- '<code>[&plusmn;]<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&le;<var>hh</var>&le;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 &minus;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>"&lt;-02&gt;2&lt;-01&gt;,M3.5.0/-1,M10.5.0/0"</code>
+- where the transition time &minus;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 &ndash; 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 &ndash; 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(&amp;clock)-&gt;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" &ndash; 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 &ndash;
+-namely, at calls to <code>localtime</code> and analogous functions &ndash;
++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&ndash;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&ndash;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-----