diff --git a/lib/libc/sys/access.2 b/lib/libc/sys/access.2 --- a/lib/libc/sys/access.2 +++ b/lib/libc/sys/access.2 @@ -28,7 +28,7 @@ .\" @(#)access.2 8.2 (Berkeley) 4/1/94 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt ACCESS 2 .Os .Sh NAME @@ -120,15 +120,10 @@ The checks for accessibility are performed using the effective user and group IDs instead of the real user and group ID as required in a call to .Fn access . -.It Dv AT_BENEATH -Only operate on files and directories below the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -218,17 +213,6 @@ directory outside of the directory hierarchy specified by .Fa fd , and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn faccessat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. .El .Sh SEE ALSO .Xr chmod 2 , diff --git a/lib/libc/sys/chflags.2 b/lib/libc/sys/chflags.2 --- a/lib/libc/sys/chflags.2 +++ b/lib/libc/sys/chflags.2 @@ -28,7 +28,7 @@ .\" @(#)chflags.2 8.3 (Berkeley) 5/2/95 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt CHFLAGS 2 .Os .Sh NAME @@ -94,16 +94,10 @@ If .Fa path names a symbolic link, then the flags of the symbolic link are changed. -.It Dv AT_BENEATH -Only allow to change flags for a file which is beneath of -the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -327,18 +321,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn chflagsat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr chflags 1 , diff --git a/lib/libc/sys/chmod.2 b/lib/libc/sys/chmod.2 --- a/lib/libc/sys/chmod.2 +++ b/lib/libc/sys/chmod.2 @@ -28,7 +28,7 @@ .\" @(#)chmod.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt CHMOD 2 .Os .Sh NAME @@ -101,16 +101,10 @@ If .Fa path names a symbolic link, then the mode of the symbolic link is changed. -.It Dv AT_BENEATH -Only allow to change permissions of a file which is beneath of -the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -310,18 +304,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn fchmodat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr chmod 1 , diff --git a/lib/libc/sys/chown.2 b/lib/libc/sys/chown.2 --- a/lib/libc/sys/chown.2 +++ b/lib/libc/sys/chown.2 @@ -28,7 +28,7 @@ .\" @(#)chown.2 8.4 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt CHOWN 2 .Os .Sh NAME @@ -118,16 +118,10 @@ If .Fa path names a symbolic link, ownership of the symbolic link is changed. -.It Dv AT_BENEATH -Only allow to change ownership of a file which is beneath of -the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -252,18 +246,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn fchownat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr chgrp 1 , diff --git a/lib/libc/sys/fhlink.2 b/lib/libc/sys/fhlink.2 --- a/lib/libc/sys/fhlink.2 +++ b/lib/libc/sys/fhlink.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt FHLINK 2 .Os .Sh NAME @@ -95,33 +95,6 @@ .Fa tofd instead of the current working directory. .Pp -Values for -.Fa flag -are constructed by a bitwise-inclusive OR of flags from the following -list, defined in -.In fcntl.h : -.Bl -tag -width indent -.It Dv AT_SYMLINK_FOLLOW -If -.Fa fhp -names a symbolic link, a new link for the target of the symbolic link is -created. -.It Dv AT_BENEATH -Only allow to link to a file which is beneath of the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. -.It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. -See the description of the -.Dv O_RESOLVE_BENEATH -flag in the -.Xr open 2 -manual page. -.El -.Pp If .Fn fhlinkat is passed the special value diff --git a/lib/libc/sys/getfh.2 b/lib/libc/sys/getfh.2 --- a/lib/libc/sys/getfh.2 +++ b/lib/libc/sys/getfh.2 @@ -29,7 +29,7 @@ .\" @(#)getfh.2 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt GETFH 2 .Os .Sh NAME @@ -76,9 +76,7 @@ .Fn lgetfh except when the .Fa path -specifies a relative path, or the -.Dv AT_BENEATH -flag is provided. +specifies a relative path. For .Fn getfhat and relative @@ -87,13 +85,6 @@ the directory associated with the file descriptor .Fa fd instead of the current working directory. -For -.Dv AT_BENEATH -and absolute -.Fa path , -the status is retrieved from a file specified by the -.Fa path , -but additional permission checks are performed, see below. .Pp The values for the .Fa flag @@ -105,13 +96,6 @@ If .Fa path names a symbolic link, the status of the symbolic link is returned. -.It Dv AT_BENEATH -Only stat files and directories below the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH Only walks paths below the topping directory. See the description of the @@ -140,19 +124,10 @@ When .Fn getfhat is called with an absolute -.Fa path -without the -.Dv AT_BENEATH -flag, it ignores the -.Fa fd -argument. -When -.Dv AT_BENEATH -is specified with an absolute .Fa path , -a directory passed by the +it ignores the .Fa fd -argument is used as the topping point for the resolution. +argument. These system calls are restricted to the superuser. .Sh RETURN VALUES .Rv -std diff --git a/lib/libc/sys/link.2 b/lib/libc/sys/link.2 --- a/lib/libc/sys/link.2 +++ b/lib/libc/sys/link.2 @@ -28,7 +28,7 @@ .\" @(#)link.2 8.3 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt LINK 2 .Os .Sh NAME @@ -115,15 +115,10 @@ .Fa name1 names a symbolic link, a new link for the target of the symbolic link is created. -.It Dv AT_BENEATH -Only allow to link to a file which is beneath of the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -281,18 +276,9 @@ is absolute or includes a ".." component that escapes the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fa linkat -and the absolute path -.Fa name1 -does not have its tail fully contained under the topping directory, -or the relative path -.Fa name1 -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr chflags 2 , diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2 --- a/lib/libc/sys/open.2 +++ b/lib/libc/sys/open.2 @@ -28,7 +28,7 @@ .\" @(#)open.2 8.2 (Berkeley) 11/16/93 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt OPEN 2 .Os .Sh NAME @@ -75,9 +75,7 @@ .Fn open function except in the case where the .Fa path -specifies a relative path, or the -.Dv O_BENEATH -flag is provided. +specifies a relative path. For .Fn openat and relative @@ -104,28 +102,10 @@ When .Fn openat is called with an absolute -.Fa path -without the -.Dv O_BENEATH -flag, it ignores the -.Fa fd -argument. -When -.Dv O_BENEATH -is specified with an absolute .Fa path , -a directory passed by the -.Fa fd -argument is used as the topping point for the resolution. -When -.Dv O_BENEATH -is specified with a relative path, the +it ignores the .Fa fd -argument is used both as the starting point, and as the topping point -for the resolution. -See the definition of the -.Dv O_BENEATH -flag below. +argument. .Pp In .Xr capsicum 4 @@ -137,9 +117,7 @@ argument to .Fn openat must be strictly relative to a file descriptor -.Fa fd , -as defined in -.Pa sys/kern/vfs_lookup.c . +.Fa fd . .Fa path must not be an absolute path and must not contain ".." components which cause the path resolution to escape the directory hierarchy @@ -156,9 +134,8 @@ .Dv vfs.lookup_cap_dotdot .Xr sysctl 3 MIB is set to zero, ".." components in the paths, -used in capability mode, or with the -.Dv O_BENEATH -flag, are completely disabled. +used in capability mode, +are completely disabled. If the .Dv vfs.lookup_cap_dotdot_nonlocal MIB is set to zero, ".." is not allowed if found on non-local filesystem. @@ -190,8 +167,7 @@ O_DIRECTORY error if file is not a directory O_CLOEXEC set FD_CLOEXEC upon open O_VERIFY verify the contents of the file -O_BENEATH require resolved path to be strictly relative to topping directory -O_RESOLVE_BENEATH require walked path to be strictly relative to topping directory +O_RESOLVE_BENEATH path resolution must not cross the fd directory .Ed .Pp Opening a file with @@ -319,32 +295,12 @@ The run-time linker (rtld) uses this flag to ensure shared objects have been verified before operating on them. .Pp -.Dv O_BENEATH -returns -.Er ENOTCAPABLE -if the specified path, after resolving all symlinks and ".." -references, does not end up with tail residing in the directory hierarchy of -children beneath the topping directory. -Topping directory is the process current directory if relative -.Fa path -is used for -.Fn open , -and the directory referenced by the -.Fa fd -argument when using -.Fn openat . -.Dv O_BENEATH -allows arbitrary prefix that ends up at the topping directory, -after which all further resolved components must be under it. -.Pp .Dv O_RESOLVE_BENEATH returns .Er ENOTCAPABLE if any intermediate component of the specified relative path does not -reside in the directory hierarchy beneath the topping directory. -Comparing to -.Dv O_BENEATH , -absolute paths or even the temporal escape from beneath of the topping +reside in the directory hierarchy beneath the starting directory. +Absolute paths or even the temporal escape from beneath of the starting directory is not allowed. .Pp When @@ -601,19 +557,12 @@ and the process is in capability mode. .It Bq Er ENOTCAPABLE The -.Dv O_BENEATH -flag was provided, and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. -.It Bq Er ENOTCAPABLE -The .Dv O_RESOLVE_BENEATH flag was provided, and the relative .Fa path -escapes topping directory. +escapes the +.Ar fd +directory. .El .Sh SEE ALSO .Xr chmod 2 , diff --git a/lib/libc/sys/stat.2 b/lib/libc/sys/stat.2 --- a/lib/libc/sys/stat.2 +++ b/lib/libc/sys/stat.2 @@ -28,7 +28,7 @@ .\" @(#)stat.2 8.4 (Berkeley) 5/1/95 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt STAT 2 .Os .Sh NAME @@ -84,9 +84,7 @@ .Fn lstat except when the .Fa path -specifies a relative path, or the -.Dv AT_BENEATH -flag is provided. +specifies a relative path. For .Fn fstatat and relative @@ -95,13 +93,6 @@ the directory associated with the file descriptor .Fa fd instead of the current working directory. -For -.Dv AT_BENEATH -and absolute -.Fa path , -the status is retrieved from a file specified by the -.Fa path , -but additional permission checks are performed, see below. .Pp The values for the .Fa flag @@ -113,15 +104,8 @@ If .Fa path names a symbolic link, the status of the symbolic link is returned. -.It Dv AT_BENEATH -Only stat files and directories below the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the starting directory. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -148,19 +132,10 @@ When .Fn fstatat is called with an absolute -.Fa path -without the -.Dv AT_BENEATH -flag, it ignores the -.Fa fd -argument. -When -.Dv AT_BENEATH -is specified with an absolute .Fa path , -a directory passed by the +it ignores the .Fa fd -argument is used as the topping point for the resolution. +argument. .Pp The .Fa sb @@ -459,18 +434,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn fstatat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr access 2 , diff --git a/lib/libc/sys/unlink.2 b/lib/libc/sys/unlink.2 --- a/lib/libc/sys/unlink.2 +++ b/lib/libc/sys/unlink.2 @@ -28,7 +28,7 @@ .\" @(#)unlink.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt UNLINK 2 .Os .Sh NAME @@ -92,16 +92,10 @@ and .Fa path as a directory, not a normal file. -.It Dv AT_BENEATH -Only unlink files and directories which are beneath of the topping -directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -246,18 +240,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn unlinkat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Pp In addition to the errors returned by diff --git a/lib/libc/sys/utimensat.2 b/lib/libc/sys/utimensat.2 --- a/lib/libc/sys/utimensat.2 +++ b/lib/libc/sys/utimensat.2 @@ -31,7 +31,7 @@ .\" @(#)utimes.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 23, 2020 +.Dd February 23, 2021 .Dt UTIMENSAT 2 .Os .Sh NAME @@ -146,16 +146,10 @@ By default, .Fn utimensat changes the times of the file referenced by the symbolic link. -.It Dv AT_BENEATH -Only allow to change the times of a file which is beneath of -the topping directory. -See the description of the -.Dv O_BENEATH -flag in the -.Xr open 2 -manual page. .It Dv AT_RESOLVE_BENEATH -Only walks paths below the topping directory. +Only walks paths below the directory specified by the +.Ar fd +descriptor. See the description of the .Dv O_RESOLVE_BENEATH flag in the @@ -290,18 +284,9 @@ or contained a ".." component leading to a directory outside of the directory hierarchy specified by .Fa fd , -and the process is in capability mode. -.It Bq Er ENOTCAPABLE -The -.Dv AT_BENEATH -flag was provided to -.Fn utimensat , -and the absolute -.Fa path -does not have its tail fully contained under the topping directory, -or the relative -.Fa path -escapes it. +and the process is in capability mode or the +.Dv AT_RESOLVE_BENEATH +flag was specified. .El .Sh SEE ALSO .Xr chflags 2 , diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -182,13 +182,9 @@ if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR) return; cnp = &ndp->ni_cnd; - if ((cnp->cn_flags & BENEATH) != 0 && - (ndp->ni_lcf & NI_LCF_BENEATH_LATCHED) == 0) { - MPASS((ndp->ni_lcf & NI_LCF_LATCH) != 0); - if (dp != ndp->ni_beneath_latch) - return; - ndp->ni_lcf |= NI_LCF_BENEATH_LATCHED; - } + nt = TAILQ_LAST(&ndp->ni_cap_tracker, nameicap_tracker_head); + if (nt != NULL && nt->dp == dp) + return; nt = malloc(sizeof(*nt), M_NAMEITRACKER, M_WAITOK); vhold(dp); nt->dp = dp; @@ -196,21 +192,24 @@ } static void -nameicap_cleanup(struct nameidata *ndp, bool clean_latch) +nameicap_cleanup_from(struct nameidata *ndp, struct nameicap_tracker *first) { struct nameicap_tracker *nt, *nt1; - KASSERT(TAILQ_EMPTY(&ndp->ni_cap_tracker) || - (ndp->ni_lcf & NI_LCF_CAP_DOTDOT) != 0, ("not strictrelative")); - TAILQ_FOREACH_SAFE(nt, &ndp->ni_cap_tracker, nm_link, nt1) { + nt = first; + TAILQ_FOREACH_FROM_SAFE(nt, &ndp->ni_cap_tracker, nm_link, nt1) { TAILQ_REMOVE(&ndp->ni_cap_tracker, nt, nm_link); vdrop(nt->dp); free(nt, M_NAMEITRACKER); } - if (clean_latch && (ndp->ni_lcf & NI_LCF_LATCH) != 0) { - ndp->ni_lcf &= ~NI_LCF_LATCH; - vrele(ndp->ni_beneath_latch); - } +} + +static void +nameicap_cleanup(struct nameidata *ndp) +{ + KASSERT(TAILQ_EMPTY(&ndp->ni_cap_tracker) || + (ndp->ni_lcf & NI_LCF_CAP_DOTDOT) != 0, ("not strictrelative")); + nameicap_cleanup_from(ndp, NULL); } /* @@ -230,23 +229,23 @@ struct nameicap_tracker *nt; struct mount *mp; - if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp == NULL || - dp->v_type != VDIR) + if (dp == NULL || dp->v_type != VDIR || (ndp->ni_lcf & + NI_LCF_STRICTRELATIVE) == 0) return (0); + if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0) + return (ENOTCAPABLE); mp = dp->v_mount; if (lookup_cap_dotdot_nonlocal == 0 && mp != NULL && (mp->mnt_flag & MNT_LOCAL) == 0) return (ENOTCAPABLE); TAILQ_FOREACH_REVERSE(nt, &ndp->ni_cap_tracker, nameicap_tracker_head, nm_link) { - if ((ndp->ni_lcf & NI_LCF_LATCH) != 0 && - ndp->ni_beneath_latch == nt->dp) { - ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED; - nameicap_cleanup(ndp, false); + if (dp == nt->dp) { + nt = TAILQ_NEXT(nt, nm_link); + if (nt != NULL) + nameicap_cleanup_from(ndp, nt); return (0); } - if (dp == nt->dp) - return (0); } return (ENOTCAPABLE); } @@ -275,11 +274,6 @@ #endif return (ENOTCAPABLE); } - if ((cnp->cn_flags & BENEATH) != 0) { - ndp->ni_lcf |= NI_LCF_BENEATH_ABS; - ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED; - nameicap_cleanup(ndp, false); - } while (*(cnp->cn_nameptr) == '/') { cnp->cn_nameptr++; ndp->ni_pathlen--; @@ -297,7 +291,6 @@ struct thread *td; struct pwd *pwd; cap_rights_t rights; - struct filecaps dirfd_caps; int error; bool startdir_used; @@ -410,26 +403,8 @@ if (error == 0 && (*dpp)->v_type != VDIR) error = ENOTDIR; } - if (error == 0 && (cnp->cn_flags & BENEATH) != 0) { - if (ndp->ni_dirfd == AT_FDCWD) { - ndp->ni_beneath_latch = pwd->pwd_cdir; - vrefact(ndp->ni_beneath_latch); - } else { - rights = *ndp->ni_rightsneeded; - cap_rights_set_one(&rights, CAP_LOOKUP); - error = fgetvp_rights(td, ndp->ni_dirfd, &rights, - &dirfd_caps, &ndp->ni_beneath_latch); - if (error == 0 && (*dpp)->v_type != VDIR) { - vrele(ndp->ni_beneath_latch); - error = ENOTDIR; - } - } - if (error == 0) - ndp->ni_lcf |= NI_LCF_LATCH; - } if (error == 0 && (cnp->cn_flags & RBENEATH) != 0) { - if (cnp->cn_pnbuf[0] == '/' || - (ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) { + if (cnp->cn_pnbuf[0] == '/') { error = EINVAL; } else if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0) { ndp->ni_lcf |= NI_LCF_STRICTRELATIVE | @@ -452,12 +427,8 @@ pwd_drop(pwd); return (error); } - MPASS((ndp->ni_lcf & (NI_LCF_BENEATH_ABS | NI_LCF_LATCH)) != - NI_LCF_BENEATH_ABS); - if (((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && - lookup_cap_dotdot != 0) || - ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0 && - (cnp->cn_flags & BENEATH) != 0)) + if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && + lookup_cap_dotdot != 0) ndp->ni_lcf |= NI_LCF_CAP_DOTDOT; SDT_PROBE4(vfs, namei, lookup, entry, *dpp, cnp->cn_pnbuf, cnp->cn_flags, false); @@ -636,16 +607,8 @@ for (;;) { ndp->ni_startdir = dp; error = lookup(ndp); - if (error != 0) { - /* - * Override an error to not allow user to use - * BENEATH as an oracle. - */ - if ((ndp->ni_lcf & (NI_LCF_LATCH | - NI_LCF_BENEATH_LATCHED)) == NI_LCF_LATCH) - error = ENOTCAPABLE; + if (error != 0) goto out; - } /* * If not a symbolic link, we're done. @@ -657,12 +620,7 @@ namei_cleanup_cnp(cnp); } else cnp->cn_flags |= HASBUF; - if ((ndp->ni_lcf & (NI_LCF_LATCH | - NI_LCF_BENEATH_LATCHED)) == NI_LCF_LATCH) { - NDFREE(ndp, 0); - error = ENOTCAPABLE; - } - nameicap_cleanup(ndp, true); + nameicap_cleanup(ndp); pwd_drop(pwd); if (error == 0) NDVALIDATE(ndp); @@ -739,7 +697,7 @@ MPASS(error != 0); SDT_PROBE4(vfs, namei, lookup, return, error, NULL, false, ndp); namei_cleanup_cnp(cnp); - nameicap_cleanup(ndp, true); + nameicap_cleanup(ndp); pwd_drop(pwd); return (error); } @@ -1314,7 +1272,8 @@ } } if (ndp->ni_vp != NULL) { - nameicap_tracker_add(ndp, ndp->ni_vp); + if ((cnp->cn_flags & ISDOTDOT) == 0) + nameicap_tracker_add(ndp, ndp->ni_vp); if ((cnp->cn_flags & (FAILIFEXISTS | ISSYMLINK)) == FAILIFEXISTS) goto bad_eexist; } 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 @@ -120,8 +120,6 @@ res = 0; at_flags &= mask; - if ((at_flags & AT_BENEATH) != 0) - res |= BENEATH; if ((at_flags & AT_RESOLVE_BENEATH) != 0) res |= RBENEATH; if ((at_flags & AT_SYMLINK_FOLLOW) != 0) @@ -1498,12 +1496,11 @@ int flag; flag = uap->flag; - if ((flag & ~(AT_SYMLINK_FOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((flag & ~(AT_SYMLINK_FOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2, - UIO_USERSPACE, at2cnpflags(flag, AT_SYMLINK_FOLLOW | AT_BENEATH | + UIO_USERSPACE, at2cnpflags(flag, AT_SYMLINK_FOLLOW | AT_RESOLVE_BENEATH))); } @@ -1873,7 +1870,7 @@ restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 | - at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH), + at2cnpflags(flag, AT_RESOLVE_BENEATH), pathseg, path, dfd, &cap_unlinkat_rights, td); if ((error = namei(&nd)) != 0) { if (error == EINVAL) @@ -2078,7 +2075,7 @@ struct nameidata nd; int error; - if ((flag & ~(AT_EACCESS | AT_BENEATH | AT_RESOLVE_BENEATH)) != 0) + if ((flag & ~(AT_EACCESS | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); if (amode != F_OK && (amode & ~(R_OK | W_OK | X_OK)) != 0) return (EINVAL); @@ -2099,7 +2096,7 @@ usecred = cred; AUDIT_ARG_VALUE(amode); NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | - AUDITVNODE1 | at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH), + AUDITVNODE1 | at2cnpflags(flag, AT_RESOLVE_BENEATH), pathseg, path, fd, &cap_fstat_rights, td); if ((error = namei(&nd)) != 0) goto out; @@ -2390,13 +2387,12 @@ struct nameidata nd; int error; - if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); - NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_BENEATH | - AT_RESOLVE_BENEATH | AT_SYMLINK_NOFOLLOW) | LOCKSHARED | LOCKLEAF | - AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights, td); + NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_RESOLVE_BENEATH | + AT_SYMLINK_NOFOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, + pathseg, path, fd, &cap_fstat_rights, td); if ((error = namei(&nd)) != 0) return (error); @@ -2714,8 +2710,7 @@ sys_chflagsat(struct thread *td, struct chflagsat_args *uap) { - if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE, @@ -2748,7 +2743,7 @@ AUDIT_ARG_FFLAGS(flags); NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(atflag, AT_SYMLINK_NOFOLLOW | - AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, + AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, &cap_fchflags_rights, td); if ((error = namei(&nd)) != 0) return (error); @@ -2843,8 +2838,7 @@ sys_fchmodat(struct thread *td, struct fchmodat_args *uap) { - if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE, @@ -2877,7 +2871,7 @@ AUDIT_ARG_MODE(mode); NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW | - AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, + AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, &cap_fchmod_rights, td); if ((error = namei(&nd)) != 0) return (error); @@ -2972,8 +2966,7 @@ sys_fchownat(struct thread *td, struct fchownat_args *uap) { - if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid, @@ -2989,7 +2982,7 @@ AUDIT_ARG_OWNER(uid, gid); NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW | - AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, + AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, &cap_fchown_rights, td); if ((error = namei(&nd)) != 0) @@ -3341,14 +3334,13 @@ struct timespec ts[2]; int error, flags; - if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0) return (error); NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_SYMLINK_NOFOLLOW | - AT_BENEATH | AT_RESOLVE_BENEATH) | AUDITVNODE1, + AT_RESOLVE_BENEATH) | AUDITVNODE1, pathseg, path, fd, &cap_futimes_rights, td); if ((error = namei(&nd)) != 0) return (error); @@ -3835,7 +3827,7 @@ restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 | - at2cnpflags(flag, AT_BENEATH | AT_RESOLVE_BENEATH), + at2cnpflags(flag, AT_RESOLVE_BENEATH), pathseg, path, dfd, &cap_unlinkat_rights, td); if ((error = namei(&nd)) != 0) goto fdout; @@ -4322,8 +4314,7 @@ sys_getfhat(struct thread *td, struct getfhat_args *uap) { - if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH | - AT_RESOLVE_BENEATH)) != 0) + if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) return (EINVAL); return (kern_getfhat(td, uap->flags, uap->fd, uap->path, UIO_USERSPACE, uap->fhp, UIO_USERSPACE)); @@ -4342,8 +4333,8 @@ if (error != 0) return (error); NDINIT_AT(&nd, LOOKUP, at2cnpflags(flags, AT_SYMLINK_NOFOLLOW | - AT_BENEATH | AT_RESOLVE_BENEATH) | LOCKLEAF | AUDITVNODE1, - pathseg, path, fd, td); + AT_RESOLVE_BENEATH) | LOCKLEAF | AUDITVNODE1, pathseg, path, + fd, td); error = namei(&nd); if (error != 0) return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -199,8 +199,6 @@ uint64_t res; res = ISOPEN | LOCKLEAF; - if ((fmode & O_BENEATH) != 0) - res |= BENEATH; if ((fmode & O_RESOLVE_BENEATH) != 0) res |= RBENEATH; if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -135,10 +135,9 @@ #if __BSD_VISIBLE #define O_VERIFY 0x00200000 /* open only after verification */ -#define O_BENEATH 0x00400000 /* Fail if not under cwd */ -#define O_RESOLVE_BENEATH 0x00800000 /* As O_BENEATH, but do not allow - resolve to walk out of cwd even to - return back */ +#define O_UNUSED1 0x00400000 /* Was O_BENEATH */ +#define O_RESOLVE_BENEATH 0x00800000 /* Do not allow name resolution to walk + out of cwd */ #endif #define O_DSYNC 0x01000000 /* POSIX data sync */ @@ -220,10 +219,9 @@ #define AT_SYMLINK_NOFOLLOW 0x0200 /* Do not follow symbolic links */ #define AT_SYMLINK_FOLLOW 0x0400 /* Follow symbolic link */ #define AT_REMOVEDIR 0x0800 /* Remove directory instead of file */ -#define AT_BENEATH 0x1000 /* Fail if not under dirfd */ -#define AT_RESOLVE_BENEATH 0x2000 /* As AT_BENEATH, but do not allow - resolve to walk out of dirfd even - to return back */ +#define AT_UNUSED1 0x1000 /* Was AT_BENEATH */ +#define AT_RESOLVE_BENEATH 0x2000 /* Do not allow name resolution + to walk out of dirfd */ #endif /* diff --git a/sys/sys/namei.h b/sys/sys/namei.h --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -111,7 +111,6 @@ */ struct componentname ni_cnd; struct nameicap_tracker_head ni_cap_tracker; - struct vnode *ni_beneath_latch; }; #ifdef _KERNEL @@ -145,7 +144,6 @@ #define WANTPARENT 0x0010 /* want parent vnode returned unlocked */ #define FAILIFEXISTS 0x0020 /* return EEXIST if found */ #define FOLLOW 0x0040 /* follow symbolic links */ -#define BENEATH 0x0080 /* No escape from the start dir */ #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 */ @@ -206,9 +204,6 @@ */ #define NI_LCF_STRICTRELATIVE 0x0001 /* relative lookup only */ #define NI_LCF_CAP_DOTDOT 0x0002 /* ".." in strictrelative case */ -#define NI_LCF_BENEATH_ABS 0x0004 /* BENEATH with absolute path */ -#define NI_LCF_BENEATH_LATCHED 0x0008 /* BENEATH_ABS traversed starting dir */ -#define NI_LCF_LATCH 0x0010 /* ni_beneath_latch valid */ /* * Initialization of a nameidata structure.