diff --git a/bin/ln/symlink.7 b/bin/ln/symlink.7 index 1789cbe5bc80..28d9908f2053 100644 --- a/bin/ln/symlink.7 +++ b/bin/ln/symlink.7 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 16, 2015 +.Dd August 11, 2024 .Dt SYMLINK 7 .Os .Sh NAME @@ -144,6 +144,7 @@ unless given the .Dv AT_SYMLINK_NOFOLLOW flag: .Xr chflagsat 2 , +.Xr faccessat 2 , .Xr fchmodat 2 , .Xr fchownat 2 , .Xr fstatat 2 diff --git a/lib/libsys/access.2 b/lib/libsys/access.2 index 46c00362a574..94a13dcc4dcf 100644 --- a/lib/libsys/access.2 +++ b/lib/libsys/access.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 21, 2024 +.Dd August 11, 2024 .Dt ACCESS 2 .Os .Sh NAME @@ -154,6 +154,10 @@ If is equal to .Dv AT_FDCWD , operate on the current working directory. +.It Dv AT_SYMLINK_NOFOLLOW +If +.Fa path +names a symbolic link, access of the symbolic link is evaluated. .El .Pp Even if a process's real or effective user has appropriate privileges diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 5f510004c684..246bc26d85d4 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -636,8 +636,8 @@ linux_faccessat2(struct thread *td, struct linux_faccessat2_args *args) { int flags, unsupported; - /* XXX. AT_SYMLINK_NOFOLLOW is not supported by kern_accessat */ - unsupported = args->flags & ~(LINUX_AT_EACCESS | LINUX_AT_EMPTY_PATH); + unsupported = args->flags & ~(LINUX_AT_EACCESS | LINUX_AT_EMPTY_PATH | + LINUX_AT_SYMLINK_NOFOLLOW); if (unsupported != 0) { linux_msg(td, "faccessat2 unsupported flag 0x%x", unsupported); return (EINVAL); @@ -647,6 +647,8 @@ linux_faccessat2(struct thread *td, struct linux_faccessat2_args *args) AT_EACCESS; flags |= (args->flags & LINUX_AT_EMPTY_PATH) == 0 ? 0 : AT_EMPTY_PATH; + flags |= (args->flags & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 : + AT_SYMLINK_NOFOLLOW; return (linux_do_accessat(td, args->dfd, args->filename, args->amode, flags)); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index c9a039515a77..28ab3080c075 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2151,7 +2151,8 @@ kern_accessat(struct thread *td, int fd, const char *path, struct nameidata nd; int error; - if ((flag & ~(AT_EACCESS | AT_RESOLVE_BENEATH | AT_EMPTY_PATH)) != 0) + if ((flag & ~(AT_EACCESS | AT_RESOLVE_BENEATH | AT_EMPTY_PATH | + AT_SYMLINK_NOFOLLOW)) != 0) return (EINVAL); if (amode != F_OK && (amode & ~(R_OK | W_OK | X_OK)) != 0) return (EINVAL); @@ -2171,8 +2172,8 @@ kern_accessat(struct thread *td, int fd, const char *path, } else usecred = cred; AUDIT_ARG_VALUE(amode); - NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | - AUDITVNODE1 | at2cnpflags(flag, AT_RESOLVE_BENEATH | + NDINIT_ATRIGHTS(&nd, LOOKUP, LOCKSHARED | LOCKLEAF | + AUDITVNODE1 | at2cnpflags(flag, AT_RESOLVE_BENEATH | AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH), pathseg, path, fd, &cap_fstat_rights); if ((error = namei(&nd)) != 0) goto out;