Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142976513
D50371.id54425.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D50371.id54425.diff
View Options
diff --git a/lib/libsys/fcntl.2 b/lib/libsys/fcntl.2
--- a/lib/libsys/fcntl.2
+++ b/lib/libsys/fcntl.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 7, 2021
+.Dd June 5, 2025
.Dt FCNTL 2
.Os
.Sh NAME
@@ -80,6 +80,11 @@
to remain open across
.Xr execve 2
system calls.
+.It
+The
+.Dv FD_RESOLVE_BENEATH
+flag, described below, will be set if it was set on the original
+descriptor.
.El
.It Dv F_DUPFD_CLOEXEC
Like
@@ -113,29 +118,47 @@
instead of
.Dv F_DUP2FD .
.It Dv F_GETFD
-Get the close-on-exec flag associated with the file descriptor
-.Fa fd
-as
-.Dv FD_CLOEXEC .
-If the returned value ANDed with
-.Dv FD_CLOEXEC
-is 0,
-the file will remain open across
-.Fn exec ,
-otherwise the file will be closed upon execution of
+Get the flags associated with the file descriptor
+.Fa fd .
+The following flags are defined:
+.Bl -tag -width FD_RESOLVE_BENEATH
+.It Dv FD_CLOEXEC
+The file will be closed upon execution of
.Fn exec
.Fa ( arg
is ignored).
+Otherwise, the file descriptor will remain open.
+.It Dv FD_RESOLVE_BENEATH
+All path name lookups relative to that file descriptor
+will behave as if the lookup had
+.Dv O_RESOLVE_BENEATH
+or
+.Dv AT_RESOLVE_BENEATH
+semantics.
+It is not permitted to call
+.Xr fchdir 2
+or
+.Xr fchroot 2
+on such a file descriptor.
+The
+.Dv FD_RESOLVE_BENEATH
+flag is sticky, meaning that it is preserved by
+.Xr dup 2
+and similar operations, and opening a directory with
+.Xr openat 2
+where the directory descriptor has the flag set causes the new directory
+descriptor to also have the flag set.
+.El
.It Dv F_SETFD
-Set the close-on-exec flag associated with
-.Fa fd
-to
-.Fa arg ,
-where
-.Fa arg
-is either 0 or
-.Dv FD_CLOEXEC ,
-as described above.
+Set flags associated with
+.Fa fd .
+The available flags are
+.Dv FD_CLOEXEC
+and
+.Dv FD_RESOLVE_BENEATH .
+The
+.Dv FD_RESOLVE_BENEATH
+flag cannot be cleared once set.
.It Dv F_GETFL
Get descriptor status flags, as described below
.Fa ( arg
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -502,7 +502,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) {
/*
@@ -639,7 +639,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;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -109,8 +109,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,
- const 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,
@@ -527,7 +527,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);
@@ -538,8 +540,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);
@@ -2164,7 +2171,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
@@ -2912,7 +2920,7 @@
#ifdef CAPABILITIES
int
fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp,
- struct file **fpp, struct filecaps *havecapsp)
+ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp)
{
struct filedesc *fdp = td->td_proc->p_fd;
int error;
@@ -2921,7 +2929,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,10 +2961,10 @@
#else
int
fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp,
- struct file **fpp, struct filecaps *havecapsp)
+ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp)
{
int error;
- error = fget_unlocked(td, fd, needrightsp, fpp);
+ error = fget_unlocked(td, fd, needrightsp, flagsp, fpp);
if (havecapsp != NULL && error == 0)
filecaps_fill(havecapsp);
@@ -3038,7 +3047,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;
@@ -3048,7 +3057,7 @@
const cap_rights_t *haverights;
cap_rights_t rights;
seqc_t seq;
- int fd;
+ int fd, flags;
VFS_SMR_ASSERT_ENTERED();
@@ -3068,7 +3077,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);
@@ -3102,17 +3113,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();
@@ -3121,9 +3134,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);
+ flags = fp->f_flag & FSEARCH;
+ flags |= (fde->fde_flags & UF_RESOLVE_BENEATH) != 0 ?
+ O_RESOLVE_BENEATH : 0;
*fsearch = ((fp->f_flag & FSEARCH) != 0);
vp = fp->f_vnode;
if (__predict_false(vp == NULL || vp->v_type != VDIR)) {
@@ -3139,6 +3156,7 @@
return (EAGAIN);
filecaps_fill(&ndp->ni_filecaps);
*vpp = vp;
+ *flagsp = flags;
return (0);
}
#endif
@@ -3152,13 +3170,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)) {
@@ -3176,6 +3196,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,7 +3247,7 @@
#ifdef CAPABILITIES
static int
fget_unlocked_seq(struct thread *td, int fd, const cap_rights_t *needrightsp,
- struct file **fpp, seqc_t *seqp)
+ uint8_t *flagsp, struct file **fpp, seqc_t *seqp)
{
struct filedesc *fdp;
const struct filedescent *fde;
@@ -3232,6 +3256,7 @@
seqc_t seq;
cap_rights_t haverights;
int error;
+ uint8_t flags;
fdp = td->td_proc->p_fd;
fdt = fdp->fd_files;
@@ -3243,6 +3268,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);
@@ -3271,19 +3297,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, const cap_rights_t *needrightsp,
- struct file **fpp, seqc_t *seqp __unused)
+ 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;
@@ -3292,6 +3320,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))) {
@@ -3308,6 +3337,8 @@
break;
fdrop(fp, td);
}
+ if (flagsp != NULL)
+ *flagsp = flags;
*fpp = fp;
return (0);
}
@@ -3321,8 +3352,8 @@
* racing with itself.
*/
int
-fget_unlocked(struct thread *td, int fd, const 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
@@ -3334,6 +3365,7 @@
seqc_t seq;
const cap_rights_t *haverights;
#endif
+ uint8_t flags;
fdp = td->td_proc->p_fd;
fdt = fdp->fd_files;
@@ -3346,8 +3378,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;
@@ -3371,12 +3405,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));
}
/*
@@ -3528,7 +3571,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)) {
@@ -3583,7 +3626,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);
@@ -3645,7 +3688,7 @@
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) {
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -91,7 +91,7 @@
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)) {
diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c
--- a/sys/kern/vfs_acl.c
+++ b/sys/kern/vfs_acl.c
@@ -434,7 +434,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);
@@ -569,7 +569,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);
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -4528,17 +4528,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);
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -253,7 +253,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);
@@ -441,7 +441,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);
@@ -597,7 +597,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);
@@ -764,7 +764,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);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -370,7 +370,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;
@@ -893,12 +893,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);
@@ -1041,10 +1046,15 @@
struct vnode *vp;
struct file *fp;
int error;
+ uint8_t fdflags;
- error = getvnode_path(td, uap->fd, &cap_fchroot_rights, &fp);
+ error = getvnode_path(td, uap->fd, &cap_fchroot_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);
@@ -1309,6 +1319,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) {
@@ -2013,7 +2027,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);
}
@@ -4409,12 +4423,12 @@
*/
int
getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp,
- struct file **fpp)
+ 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);
@@ -4451,7 +4465,7 @@
{
int error;
- error = getvnode_path(td, fd, rightsp, fpp);
+ error = getvnode_path(td, fd, rightsp, NULL, fpp);
if (__predict_false(error != 0))
return (error);
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -289,6 +289,8 @@
/* file descriptor flags (F_GETFD, F_SETFD) */
#define FD_CLOEXEC 1 /* close-on-exec flag */
+#define FD_RESOLVE_BENEATH 2 /* all lookups relative to fd have
+ O_RESOLVE_BENEATH semantics */
/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */
#define F_RDLCK 1 /* shared or read lock */
diff --git a/sys/sys/file.h b/sys/sys/file.h
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -301,7 +301,7 @@
struct vnode **vpp);
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
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -148,6 +148,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
@@ -278,17 +279,20 @@
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,
- struct file **fpp);
+ uint8_t *flagsp, struct file **fpp);
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
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,
- struct file **fpp, struct filecaps *havecapsp);
+ 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,
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,
const cap_rights_t *needrightsp, struct file **fpp);
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -196,6 +196,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.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 26, 1:22 AM (14 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27966455
Default Alt Text
D50371.id54425.diff (19 KB)
Attached To
Mode
D50371: unix: Restrict dirfds exchanged between jails with a different root
Attached
Detach File
Event Timeline
Log In to Comment