[RFC][PATCH] Mark AT_* path flags as deprecated and add missing RESOLVE_ flags

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Do we want to do this?  Or should we duplicate the RESOLVE_* flags to AT_*
flags so that existing *at() syscalls can make use of them?

David
---
commit 448731bf3b29f2b1f7c969d7efe1f0673ae13b5e
Author: David Howells <dhowells@xxxxxxxxxx>
Date:   Thu Mar 5 17:40:02 2020 +0000

    Mark AT_* flags as deprecated and add missing RESOLVE_ flags
    
    It has been suggested that new path-using system calls should use RESOLVE_*
    flags instead of AT_* flags, but the RESOLVE_* flag functions are not a
    superset of the AT_* flag functions.  So formalise this by:
    
     (1) In linux/fcntl.h, add a comment noting that the AT_* flags are
         deprecated for new system calls and that RESOLVE_* flags should be
         used instead.
    
     (2) Add some missing flags:
    
            RESOLVE_NO_TERMINAL_SYMLINKS    for AT_SYMLINK_NOFOLLOW
            RESOLVE_NO_TERMINAL_AUTOMOUNTS  for AT_NO_AUTOMOUNT
            RESOLVE_EMPTY_PATH              for AT_EMPTY_PATH
    
     (3) Make openat2() support RESOLVE_NO_TERMINAL_SYMLINKS.  LOOKUP_OPEN
         internally implies LOOKUP_AUTOMOUNT, and AT_EMPTY_PATH is probably not
         worth supporting (maybe use dup2() instead?).
    
    Reported-by: Stefan Metzmacher <metze@xxxxxxxxx>
    Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
    cc: Aleksa Sarai <cyphar@xxxxxxxxxx>

diff --git a/fs/open.c b/fs/open.c
index 0788b3715731..6946ad09b42b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -977,7 +977,7 @@ inline struct open_how build_open_how(int flags, umode_t mode)
 inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 {
 	int flags = how->flags;
-	int lookup_flags = 0;
+	int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
 	int acc_mode = ACC_MODE(flags);
 
 	/* Must never be set by userspace */
@@ -1055,8 +1055,8 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 
 	if (flags & O_DIRECTORY)
 		lookup_flags |= LOOKUP_DIRECTORY;
-	if (!(flags & O_NOFOLLOW))
-		lookup_flags |= LOOKUP_FOLLOW;
+	if (flags & O_NOFOLLOW)
+		lookup_flags &= ~LOOKUP_FOLLOW;
 
 	if (how->resolve & RESOLVE_NO_XDEV)
 		lookup_flags |= LOOKUP_NO_XDEV;
@@ -1068,6 +1068,8 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 		lookup_flags |= LOOKUP_BENEATH;
 	if (how->resolve & RESOLVE_IN_ROOT)
 		lookup_flags |= LOOKUP_IN_ROOT;
+	if (how->resolve & RESOLVE_NO_TERMINAL_SYMLINKS)
+		lookup_flags &= ~LOOKUP_FOLLOW;
 
 	op->lookup_flags = lookup_flags;
 	return 0;
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 7bcdcf4f6ab2..fd6ee34cce0f 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -19,7 +19,8 @@
 /* List of all valid flags for the how->resolve argument: */
 #define VALID_RESOLVE_FLAGS \
 	(RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS | \
-	 RESOLVE_BENEATH | RESOLVE_IN_ROOT)
+	 RESOLVE_BENEATH | RESOLVE_IN_ROOT | RESOLVE_NO_TERMINAL_SYMLINKS | \
+	 RESOLVE_NO_TERMINAL_AUTOMOUNTS | RESOLVE_EMPTY_PATH)
 
 /* List of all open_how "versions". */
 #define OPEN_HOW_SIZE_VER0	24 /* sizeof first published struct */
diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h
index ca88b7bce553..9f5432dbd213 100644
--- a/include/uapi/linux/fcntl.h
+++ b/include/uapi/linux/fcntl.h
@@ -84,9 +84,20 @@
 #define DN_ATTRIB	0x00000020	/* File changed attibutes */
 #define DN_MULTISHOT	0x80000000	/* Don't remove notifier */
 
-#define AT_FDCWD		-100    /* Special value used to indicate
-                                           openat should use the current
-                                           working directory. */
+
+/*
+ * Special dfd/dirfd file descriptor value used to indicate that *at() system
+ * calls should use the current working directory for relative paths.
+ */
+#define AT_FDCWD		-100
+
+/*
+ * Pathwalk control flags, used for the *at() syscalls.  These should be
+ * considered deprecated and should not be used for new system calls.  The
+ * RESOLVE_* flags in <linux/openat2.h> should be used instead.
+ *
+ * There are also system call-specific flags here (REMOVEDIR, STATX, RECURSIVE).
+ */
 #define AT_SYMLINK_NOFOLLOW	0x100   /* Do not follow symbolic links.  */
 #define AT_REMOVEDIR		0x200   /* Remove directory instead of
                                            unlinking file.  */
diff --git a/include/uapi/linux/openat2.h b/include/uapi/linux/openat2.h
index 58b1eb711360..bb8d0a7f82c2 100644
--- a/include/uapi/linux/openat2.h
+++ b/include/uapi/linux/openat2.h
@@ -22,7 +22,10 @@ struct open_how {
 	__u64 resolve;
 };
 
-/* how->resolve flags for openat2(2). */
+/*
+ * Path resolution paths to replace AT_* paths in all new syscalls that would
+ * use them.
+ */
 #define RESOLVE_NO_XDEV		0x01 /* Block mount-point crossings
 					(includes bind-mounts). */
 #define RESOLVE_NO_MAGICLINKS	0x02 /* Block traversal through procfs-style
@@ -35,5 +38,8 @@ struct open_how {
 #define RESOLVE_IN_ROOT		0x10 /* Make all jumps to "/" and ".."
 					be scoped inside the dirfd
 					(similar to chroot(2)). */
+#define RESOLVE_NO_TERMINAL_SYMLINKS	0x20 /* Don't follow terminal symlinks in the path */
+#define RESOLVE_NO_TERMINAL_AUTOMOUNTS	0x40 /* Don't follow terminal automounts in the path */
+#define RESOLVE_EMPTY_PATH	0x80	/* Permit a path of "" to indicate the dfd exactly */
 
 #endif /* _UAPI_LINUX_OPENAT2_H */





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux