]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fd-util: refuse O_CREAT in fd_reopen
authorMike Yuan <me@yhndnzj.com>
Wed, 8 Nov 2023 17:10:06 +0000 (01:10 +0800)
committerMike Yuan <me@yhndnzj.com>
Wed, 8 Nov 2023 19:35:56 +0000 (03:35 +0800)
O_CREAT doesn't make sense for fd_reopen, since we're
working on an already opened fd. Also, in fd_reopen
we don't handle the mode parameter of open(2), which
means we may get runtime error like #29938.

src/basic/fd-util.c

index 32289cfd09ea8233d1f0f98ed14ad271b8232540..0690bcd8300fc3b752445a0ae36de8b6f5185598 100644 (file)
@@ -761,9 +761,10 @@ finish:
 }
 
 int fd_reopen(int fd, int flags) {
-        int new_fd, r;
+        int r;
 
         assert(fd >= 0 || fd == AT_FDCWD);
+        assert(!FLAGS_SET(flags, O_CREAT));
 
         /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
          * turn O_RDWR fds into O_RDONLY fds.
@@ -787,19 +788,12 @@ int fd_reopen(int fd, int flags) {
                  * the same way as the non-O_DIRECTORY case. */
                 return -ELOOP;
 
-        if (FLAGS_SET(flags, O_DIRECTORY) || fd == AT_FDCWD) {
+        if (FLAGS_SET(flags, O_DIRECTORY) || fd == AT_FDCWD)
                 /* If we shall reopen the fd as directory we can just go via "." and thus bypass the whole
                  * magic /proc/ directory, and make ourselves independent of that being mounted. */
-                new_fd = openat(fd, ".", flags | O_DIRECTORY);
-                if (new_fd < 0)
-                        return -errno;
-
-                return new_fd;
-        }
-
-        assert(fd >= 0);
+                return RET_NERRNO(openat(fd, ".", flags | O_DIRECTORY));
 
-        new_fd = open(FORMAT_PROC_FD_PATH(fd), flags);
+        int new_fd = open(FORMAT_PROC_FD_PATH(fd), flags);
         if (new_fd < 0) {
                 if (errno != ENOENT)
                         return -errno;
@@ -825,6 +819,7 @@ int fd_reopen_condition(
         int r, new_fd;
 
         assert(fd >= 0);
+        assert(!FLAGS_SET(flags, O_CREAT));
 
         /* Invokes fd_reopen(fd, flags), but only if the existing F_GETFL flags don't match the specified
          * flags (masked by the specified mask). This is useful for converting O_PATH fds into real fds if