git: 2cbb6f0c05 - main - Add SA-26:04 and SA-26:05.

Gordon Tetlow <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.doc
Message-ID <[email protected]>
The branch main has been updated by gordon:

URL: https://cgit.FreeBSD.org/doc/commit/?id=2cbb6f0c05d1872fca1d0ec949ff7b844ca1cc0d

commit 2cbb6f0c05d1872fca1d0ec949ff7b844ca1cc0d
Author:     Gordon Tetlow <[email protected]>
AuthorDate: 2026-02-24 16:26:10 +0000
Commit:     Gordon Tetlow <[email protected]>
CommitDate: 2026-02-24 16:26:10 +0000

    Add SA-26:04 and SA-26:05.
    
    Approved by:    so
---
 website/data/security/advisories.toml              |    8 +
 .../security/advisories/FreeBSD-SA-26:04.jail.asc  |  165 +++
 .../security/advisories/FreeBSD-SA-26:05.route.asc |  161 +++
 .../static/security/patches/SA-26:04/jail-13.patch | 1132 +++++++++++++++++++
 .../security/patches/SA-26:04/jail-13.patch.asc    |   16 +
 .../static/security/patches/SA-26:04/jail-14.patch | 1173 ++++++++++++++++++++
 .../security/patches/SA-26:04/jail-14.patch.asc    |   16 +
 .../static/security/patches/SA-26:05/route.patch   |   13 +
 .../security/patches/SA-26:05/route.patch.asc      |   16 +
 9 files changed, 2700 insertions(+)

diff --git a/website/data/security/advisories.toml b/website/data/security/advisories.toml
index c1c95b201a..18fcab9bf1 100644
--- a/website/data/security/advisories.toml
+++ b/website/data/security/advisories.toml
@@ -1,6 +1,14 @@
 # Sort advisories by year, month and day
 # $FreeBSD$
 
+[[advisories]]
+name = "FreeBSD-SA-26:05.route"
+date = "2026-02-24"
+
+[[advisories]]
+name = "FreeBSD-SA-26:04.jail"
+date = "2026-02-24"
+
 [[advisories]]
 name = "FreeBSD-SA-26:03.blocklistd"
 date = "2026-02-10"
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/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)
*** 1797 LINES SKIPPED ***
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.