]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fd-util: beef up fd_verify_safe_flags() features
authorLennart Poettering <lennart@poettering.net>
Tue, 27 Feb 2024 16:50:45 +0000 (17:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 11 Mar 2024 13:49:51 +0000 (14:49 +0100)
Let's make fd_verify_safe_flags() even more useful:

1. let's return the cleaned up flags (i.e. just the access mode) after
   validation, hiding all the noise, such as O_NOFOLLOW, O_LARGEFILE and
   similar.

2. let's add a "full" version of the call that allows passing additional
   flags that are OK to be set.

src/basic/fd-util.c
src/basic/fd-util.h
src/import/importd.c

index c16a2ab658e087ad041678888c0599371d6ef193..8372c54918d07159dd9643d650eb1959e9e777a5 100644 (file)
@@ -913,21 +913,21 @@ int fd_is_opath(int fd) {
         return FLAGS_SET(r, O_PATH);
 }
 
-int fd_verify_safe_flags(int fd) {
+int fd_verify_safe_flags_full(int fd, int extra_flags) {
         int flags, unexpected_flags;
 
         /* Check if an extrinsic fd is safe to work on (by a privileged service). This ensures that clients
          * can't trick a privileged service into giving access to a file the client doesn't already have
          * access to (especially via something like O_PATH).
          *
-         * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl; it doesn't go away
+         * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl(); it doesn't go away
          *             immediately after open(). It should have no effect whatsoever to an already-opened FD,
          *             and since we refuse O_PATH it should be safe.
          *
          * RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl.
          *                  See comment in missing_fcntl.h for more details about this.
          *
-         * O_DIRECTORY: this is set for directories, which are totally fine
+         * If 'extra_flags' is specified as non-zero the included flags are also allowed.
          */
 
         assert(fd >= 0);
@@ -936,13 +936,13 @@ int fd_verify_safe_flags(int fd) {
         if (flags < 0)
                 return -errno;
 
-        unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|O_DIRECTORY);
+        unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
         if (unexpected_flags != 0)
                 return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO),
                                        "Unexpected flags set for extrinsic fd: 0%o",
                                        (unsigned) unexpected_flags);
 
-        return 0;
+        return flags & (O_ACCMODE | extra_flags); /* return the flags variable, but remove the noise */
 }
 
 int read_nr_open(void) {
index f549831090a3ff3dca15d406d7bc1de7c4deb368..1e591085ef88c24e62352575b2d1aa7828239ea8 100644 (file)
@@ -114,7 +114,11 @@ int fd_reopen(int fd, int flags);
 int fd_reopen_condition(int fd, int flags, int mask, int *ret_new_fd);
 
 int fd_is_opath(int fd);
-int fd_verify_safe_flags(int fd);
+
+int fd_verify_safe_flags_full(int fd, int extra_flags);
+static inline int fd_verify_safe_flags(int fd) {
+        return fd_verify_safe_flags_full(fd, 0);
+}
 
 int read_nr_open(void);
 int fd_get_diskseq(int fd, uint64_t *ret);
index 4bba46984ae0211329a9904fccb975b89e5939cd..3bfa3cdd75215e1577d85d390ae496fbb84259e6 100644 (file)
@@ -901,7 +901,7 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e
                 SET_FLAG(flags, IMPORT_READ_ONLY, read_only);
         }
 
-        r = fd_verify_safe_flags(fd);
+        r = fd_verify_safe_flags_full(fd, O_DIRECTORY);
         if (r < 0)
                 return r;