git: 5ab6ed93cd36 - main - faccessat(2): Honor AT_SYMLINK_NOFOLLOW

From: Fernando Apesteguía <fernape_at_FreeBSD.org>
Date: Sun, 11 Aug 2024 15:54:38 UTC
The branch main has been updated by fernape:

URL: https://cgit.FreeBSD.org/src/commit/?id=5ab6ed93cd3680f8b69dd4d05823f4740a2bdef9

commit 5ab6ed93cd3680f8b69dd4d05823f4740a2bdef9
Author:     Fernando Apesteguía <fernape@FreeBSD.org>
AuthorDate: 2024-08-11 15:43:04 +0000
Commit:     Fernando Apesteguía <fernape@FreeBSD.org>
CommitDate: 2024-08-11 15:49:06 +0000

    faccessat(2): Honor AT_SYMLINK_NOFOLLOW
    
    Make the system call honor `AT_SYMLINK_NOFOLLOW`.
    
    Also enable this from `linux_faccessat2` where the issue arised the first time.
    Update manual pages accordingly.
    
    PR:                     275295
    Reported by:            kenrap@kennethraplee.com
    Approved by:            kib@
    Differential Revision:  https://reviews.freebsd.org/D46267
---
 bin/ln/symlink.7              | 3 ++-
 lib/libsys/access.2           | 6 +++++-
 sys/compat/linux/linux_file.c | 6 ++++--
 sys/kern/vfs_syscalls.c       | 7 ++++---
 4 files changed, 15 insertions(+), 7 deletions(-)

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;