Author: kib Date: Thu Oct 22 15:23:41 2020 New Revision: 366937 URL: https://svnweb.freebsd.org/changeset/base/366937
Log: MFC r339748, r340343, r340347, r341256, r366015-r366023, r366549: O_BENEATH and related features. Sponsored by: The FreeBSD Foundation Tested by: pho Modified: stable/12/lib/libc/sys/access.2 stable/12/lib/libc/sys/chflags.2 stable/12/lib/libc/sys/chmod.2 stable/12/lib/libc/sys/chown.2 stable/12/lib/libc/sys/fhlink.2 stable/12/lib/libc/sys/getfh.2 stable/12/lib/libc/sys/link.2 stable/12/lib/libc/sys/open.2 stable/12/lib/libc/sys/stat.2 stable/12/lib/libc/sys/unlink.2 stable/12/lib/libc/sys/utimensat.2 stable/12/sys/cddl/compat/opensolaris/sys/vnode.h stable/12/sys/compat/cloudabi/cloudabi_file.c stable/12/sys/compat/linux/linux_file.c stable/12/sys/kern/vfs_lookup.c stable/12/sys/kern/vfs_mountroot.c stable/12/sys/kern/vfs_syscalls.c stable/12/sys/kern/vfs_vnops.c stable/12/sys/sys/fcntl.h stable/12/sys/sys/namei.h stable/12/sys/sys/syscallsubr.h stable/12/sys/ufs/ffs/ffs_alloc.c Directory Properties: stable/12/ (props changed) Modified: stable/12/lib/libc/sys/access.2 ============================================================================== --- stable/12/lib/libc/sys/access.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/access.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)access.2 8.2 (Berkeley) 4/1/94 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt ACCESS 2 .Os .Sh NAME @@ -120,6 +120,20 @@ list, defined in 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp Even if a process's real or effective user has appropriate privileges @@ -197,6 +211,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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 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 , Modified: stable/12/lib/libc/sys/chflags.2 ============================================================================== --- stable/12/lib/libc/sys/chflags.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/chflags.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)chflags.2 8.3 (Berkeley) 5/2/95 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt CHFLAGS 2 .Os .Sh NAME @@ -94,6 +94,21 @@ defined in 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -306,6 +321,24 @@ Corrupted data was detected while reading from the fil The underlying file system does not support file flags, or does not support all of the flags set in .Fa flags . +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr chflags 1 , Modified: stable/12/lib/libc/sys/chmod.2 ============================================================================== --- stable/12/lib/libc/sys/chmod.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/chmod.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)chmod.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt CHMOD 2 .Os .Sh NAME @@ -101,6 +101,21 @@ in 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -289,6 +304,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr chmod 1 , Modified: stable/12/lib/libc/sys/chown.2 ============================================================================== --- stable/12/lib/libc/sys/chown.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/chown.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)chown.2 8.4 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt CHOWN 2 .Os .Sh NAME @@ -118,6 +118,21 @@ list, defined in 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -231,6 +246,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr chgrp 1 , Modified: stable/12/lib/libc/sys/fhlink.2 ============================================================================== --- stable/12/lib/libc/sys/fhlink.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/fhlink.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt FHLINK 2 .Os .Sh NAME @@ -110,6 +110,13 @@ created. 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. Modified: stable/12/lib/libc/sys/getfh.2 ============================================================================== --- stable/12/lib/libc/sys/getfh.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/getfh.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -29,7 +29,7 @@ .\" @(#)getfh.2 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt GETFH 2 .Os .Sh NAME @@ -109,6 +109,13 @@ names a symbolic link, the status of the symbolic link 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 +.Dv O_RESOLVE_BENEATH flag in the .Xr open 2 manual page. Modified: stable/12/lib/libc/sys/link.2 ============================================================================== --- stable/12/lib/libc/sys/link.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/link.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)link.2 8.3 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt LINK 2 .Os .Sh NAME @@ -115,6 +115,20 @@ If .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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -259,6 +273,26 @@ or respectively, is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa name1 +is not strictly relative to the starting directory. +For example, +.Fa name1 +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. .El .Sh SEE ALSO .Xr chflags 2 , Modified: stable/12/lib/libc/sys/open.2 ============================================================================== --- stable/12/lib/libc/sys/open.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/open.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)open.2 8.2 (Berkeley) 11/16/93 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt OPEN 2 .Os .Sh NAME @@ -75,8 +75,14 @@ function is equivalent to the .Fn open function except in the case where the .Fa path -specifies a relative path. -In this case the file to be opened is determined relative to the directory +specifies a relative path, or the +.Dv O_BENEATH +flag is provided. +For +.Fn openat +and relative +.Fa path , +the file to be opened is determined relative to the directory associated with the file descriptor .Fa fd instead of the current working directory. @@ -95,6 +101,32 @@ parameter, the current working directory is used and the behavior is identical to a call to .Fn open . .Pp +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 +.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. +.Pp In .Xr capsicum 4 capability mode, @@ -109,14 +141,28 @@ must be strictly relative to a file descriptor as defined in .Pa sys/kern/vfs_lookup.c . .Fa path -must not be an absolute path and must not contain ".." components. +must not be an absolute path and must not contain ".." components +which cause the path resolution to escape the directory hierarchy +starting at +.Fa fd . Additionally, no symbolic link in .Fa path -may contain ".." components either. +may target absolute path or contain escaping ".." components. .Fa fd must not be .Dv AT_FDCWD . .Pp +If the +.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. +If the +.Dv vfs.lookup_cap_dotdot_nonlocal +MIB is set to zero, ".." is not allowed if found on non-local filesystem. +.Pp The flags specified are formed by .Em or Ns 'ing the following values @@ -143,6 +189,8 @@ O_TTY_INIT ignored 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 .Ed .Pp Opening a file with @@ -266,7 +314,34 @@ The details of what means is implementation specific. The run-time linker (rtld) uses this flag to ensure shared objects have been verified before operating on them. +.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 +directory is not allowed. +.Pp When .Fa fd is opened with @@ -280,6 +355,7 @@ The primary use for this descriptor will be as the loo .Fn *at family of functions. .Pp +.Pp If successful, .Fn open returns a non-negative integer, termed a file descriptor. @@ -480,6 +556,12 @@ and .Dv O_EXEC or .Dv O_SEARCH . +.It Bq Er EINVAL +The +.Dv O_RESOLVE_BENEATH +flag is specified and +.Dv path +is absolute. .It Bq Er EBADF The .Fa path @@ -508,9 +590,26 @@ is specified and the process is in capability mode. was called and the process is in capability mode. .It Bq Er ENOTCAPABLE .Fa path -is an absolute path or contained a ".." component leading to a +is an absolute path, +or contained a ".." component leading to a directory outside of the directory hierarchy specified by -.Fa fd . +.Fa fd , +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. .El .Sh SEE ALSO .Xr chmod 2 , Modified: stable/12/lib/libc/sys/stat.2 ============================================================================== --- stable/12/lib/libc/sys/stat.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/stat.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)stat.2 8.4 (Berkeley) 5/1/95 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt STAT 2 .Os .Sh NAME @@ -84,11 +84,24 @@ and .Fn lstat except when the .Fa path -specifies a relative path. -In this case the status is retrieved from a file relative to +specifies a relative path, or the +.Dv AT_BENEATH +flag is provided. +For +.Fn fstatat +and relative +.Fa path , +the status is retrieved from a file relative to 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 @@ -100,6 +113,20 @@ defined in 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 +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -118,6 +145,23 @@ respectively, depending on whether or not the bit is set in .Fa flag . .Pp +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 +.Fa fd +argument is used as the topping point for the resolution. +.Pp The .Fa sb argument is a pointer to a @@ -409,6 +453,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr access 2 , Modified: stable/12/lib/libc/sys/unlink.2 ============================================================================== --- stable/12/lib/libc/sys/unlink.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/unlink.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -28,7 +28,7 @@ .\" @(#)unlink.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt UNLINK 2 .Os .Sh NAME @@ -89,6 +89,21 @@ Remove the directory entry specified by 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Pp If @@ -202,6 +217,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr chflags 2 , Modified: stable/12/lib/libc/sys/utimensat.2 ============================================================================== --- stable/12/lib/libc/sys/utimensat.2 Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/lib/libc/sys/utimensat.2 Thu Oct 22 15:23:41 2020 (r366937) @@ -31,7 +31,7 @@ .\" @(#)utimes.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd September 23, 2020 .Dt UTIMENSAT 2 .Os .Sh NAME @@ -146,6 +146,21 @@ names a symbolic link, the symbolic link's times are c 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. +See the description of the +.Dv O_RESOLVE_BENEATH +flag in the +.Xr open 2 +manual page. .El .Sh RETURN VALUES .Rv -std @@ -269,6 +284,24 @@ argument is not an absolute path and is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. +.It Bq Er ENOTCAPABLE +.Fa path +is an absolute path, +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. .El .Sh SEE ALSO .Xr chflags 2 , Modified: stable/12/sys/cddl/compat/opensolaris/sys/vnode.h ============================================================================== --- stable/12/sys/cddl/compat/opensolaris/sys/vnode.h Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/sys/cddl/compat/opensolaris/sys/vnode.h Thu Oct 22 15:23:41 2020 (r366937) @@ -278,7 +278,7 @@ vn_remove(char *fnamep, enum uio_seg seg, enum rm dirf ASSERT(seg == UIO_SYSSPACE); ASSERT(dirflag == RMFILE); - return (kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0)); + return (kern_unlinkat(curthread, AT_FDCWD, fnamep, seg, 0, 0)); } #endif /* _KERNEL */ Modified: stable/12/sys/compat/cloudabi/cloudabi_file.c ============================================================================== --- stable/12/sys/compat/cloudabi/cloudabi_file.c Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/sys/compat/cloudabi/cloudabi_file.c Thu Oct 22 15:23:41 2020 (r366937) @@ -752,9 +752,9 @@ cloudabi_sys_file_unlink(struct thread *td, return (error); if (uap->flags & CLOUDABI_UNLINK_REMOVEDIR) - error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE); + error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE, 0); else - error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0, 0); cloudabi_freestr(path); return (error); } Modified: stable/12/sys/compat/linux/linux_file.c ============================================================================== --- stable/12/sys/compat/linux/linux_file.c Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/sys/compat/linux/linux_file.c Thu Oct 22 15:23:41 2020 (r366937) @@ -540,7 +540,7 @@ linux_unlink(struct thread *td, struct linux_unlink_ar LCONVPATHEXIST(td, args->path, &path); - error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0, 0); if (error == EPERM) { /* Introduce POSIX noncompliant behaviour of Linux */ if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, @@ -568,9 +568,9 @@ linux_unlinkat(struct thread *td, struct linux_unlinka LCONVPATHEXIST_AT(td, args->pathname, &path, dfd); if (args->flag & LINUX_AT_REMOVEDIR) - error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE); + error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE, 0); else - error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0); + error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0, 0); if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) { /* Introduce POSIX noncompliant behaviour of Linux */ if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path, @@ -661,7 +661,7 @@ linux_rmdir(struct thread *td, struct linux_rmdir_args LCONVPATHEXIST(td, args->path, &path); - error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE); + error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE, 0); LFREEPATH(path); return (error); } Modified: stable/12/sys/kern/vfs_lookup.c ============================================================================== --- stable/12/sys/kern/vfs_lookup.c Thu Oct 22 12:22:08 2020 (r366936) +++ stable/12/sys/kern/vfs_lookup.c Thu Oct 22 15:23:41 2020 (r366937) @@ -174,9 +174,18 @@ static void nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp) { struct nameicap_tracker *nt; + struct componentname *cnp; 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 = uma_zalloc(nt_zone, M_WAITOK); vhold(dp); nt->dp = dp; @@ -184,7 +193,7 @@ nameicap_tracker_add(struct nameidata *ndp, struct vno } static void -nameicap_cleanup(struct nameidata *ndp) +nameicap_cleanup(struct nameidata *ndp, bool clean_latch) { struct nameicap_tracker *nt, *nt1; @@ -195,12 +204,20 @@ nameicap_cleanup(struct nameidata *ndp) vdrop(nt->dp); uma_zfree(nt_zone, nt); } + if (clean_latch && (ndp->ni_lcf & NI_LCF_LATCH) != 0) { + ndp->ni_lcf &= ~NI_LCF_LATCH; + vrele(ndp->ni_beneath_latch); + } } /* * For dotdot lookups in capability mode, only allow the component * lookup to succeed if the resulting directory was already traversed - * during the operation. Also fail dotdot lookups for non-local + * during the operation. This catches situations where already + * traversed directory is moved to different parent, and then we walk + * over it with dotdots. + * + * Also allow to force failure of dotdot lookups for non-local * filesystems, where external agents might assist local lookups to * escape the compartment. */ @@ -219,6 +236,12 @@ nameicap_check_dotdot(struct nameidata *ndp, struct vn 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); + return (0); + } if (dp == nt->dp) return (0); } @@ -249,6 +272,11 @@ namei_handle_root(struct nameidata *ndp, struct vnode #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--; @@ -290,6 +318,7 @@ namei(struct nameidata *ndp) struct thread *td; struct proc *p; cap_rights_t rights; + struct filecaps dirfd_caps; struct uio auio; int error, linklen, startdir_used; @@ -347,6 +376,7 @@ namei(struct nameidata *ndp) if (error == 0 && IN_CAPABILITY_MODE(td) && (cnp->cn_flags & NOCAPCHECK) == 0) { ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; + ndp->ni_resflags |= NIRES_STRICTREL; if (ndp->ni_dirfd == AT_FDCWD) { #ifdef KTRACE if (KTRPOINT(td, KTR_CAPFAIL)) @@ -441,13 +471,42 @@ namei(struct nameidata *ndp) ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL || ndp->ni_filecaps.fc_nioctls != -1) { ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; + ndp->ni_resflags |= NIRES_STRICTREL; } #endif } if (error == 0 && dp->v_type != VDIR) error = ENOTDIR; } + if (error == 0 && (cnp->cn_flags & BENEATH) != 0) { + if (ndp->ni_dirfd == AT_FDCWD) { + ndp->ni_beneath_latch = fdp->fd_cdir; + vrefact(ndp->ni_beneath_latch); + } else { + rights = ndp->ni_rightsneeded; + cap_rights_set(&rights, CAP_LOOKUP); + error = fgetvp_rights(td, ndp->ni_dirfd, &rights, + &dirfd_caps, &ndp->ni_beneath_latch); + if (error == 0 && dp->v_type != VDIR) { + vrele(ndp->ni_beneath_latch); + error = ENOTDIR; + } + } + if (error == 0) + ndp->ni_lcf |= NI_LCF_LATCH; + } FILEDESC_SUNLOCK(fdp); + + if (error == 0 && (cnp->cn_flags & RBENEATH) != 0) { + if (cnp->cn_pnbuf[0] == '/' || + (ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) { + error = EINVAL; + } else if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0) { + ndp->ni_lcf |= NI_LCF_STRICTRELATIVE | + NI_LCF_CAP_DOTDOT; + } + } + if (ndp->ni_startdir != NULL && !startdir_used) vrele(ndp->ni_startdir); if (error != 0) { @@ -455,16 +514,29 @@ namei(struct nameidata *ndp) vrele(dp); goto out; } - if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && - lookup_cap_dotdot != 0) + 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)) ndp->ni_lcf |= NI_LCF_CAP_DOTDOT; SDT_PROBE3(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf, cnp->cn_flags); for (;;) { ndp->ni_startdir = dp; error = lookup(ndp); - if (error != 0) + 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; goto out; + } + /* * If not a symbolic link, we're done. */ @@ -474,9 +546,15 @@ namei(struct nameidata *ndp) namei_cleanup_cnp(cnp); } else cnp->cn_flags |= HASBUF; - nameicap_cleanup(ndp); - SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp); - return (0); + if ((ndp->ni_lcf & (NI_LCF_LATCH | + NI_LCF_BENEATH_LATCHED)) == NI_LCF_LATCH) { + NDFREE(ndp, 0); + error = ENOTCAPABLE; + } + nameicap_cleanup(ndp, true); + SDT_PROBE2(vfs, namei, lookup, return, error, + (error == 0 ? ndp->ni_vp : NULL)); + return (error); } if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { error = ELOOP; @@ -547,8 +625,9 @@ namei(struct nameidata *ndp) vrele(ndp->ni_dvp); out: vrele(ndp->ni_rootdir); + MPASS(error != 0); *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"