]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fdset: set all collected fds to CLOEXEC in fdset_new_fill()
authorMike Yuan <me@yhndnzj.com>
Thu, 30 Nov 2023 16:00:27 +0000 (00:00 +0800)
committerMike Yuan <me@yhndnzj.com>
Thu, 30 Nov 2023 16:14:37 +0000 (00:14 +0800)
src/core/main.c
src/notify/notify.c
src/shared/fdset.c
src/test/test-fdset.c

index 2ac59dabf5a23bd9490b5e48a2843ed9e23d25a1..3f71cc094795c9e9be0677c8c253b1c153f4703a 100644 (file)
@@ -2739,8 +2739,6 @@ static int collect_fds(FDSet **ret_fds, const char **ret_error_message) {
                                         "MESSAGE_ID=" SD_MESSAGE_CORE_FD_SET_FAILED_STR);
         }
 
-        (void) fdset_cloexec(*ret_fds, true);
-
         /* The serialization fd should have O_CLOEXEC turned on already, let's verify that we didn't pick it up here */
         assert_se(!arg_serialization || !fdset_contains(*ret_fds, fileno(arg_serialization)));
 
index 675fbda752a33ad60bd12e0ee699224affaf8ede..f63ec8b355f25e648caba00dfe2f57755a3a2950 100644 (file)
@@ -225,10 +225,6 @@ static int parse_argv(int argc, char *argv[]) {
                                 r = fdset_new_fill(/* filter_cloexec= */ 0, &passed);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to take possession of passed file descriptors: %m");
-
-                                r = fdset_cloexec(passed, true);
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to enable O_CLOEXEC for passed file descriptors: %m");
                         }
 
                         if (fdnr < 3) {
index b62f15c6494fbdab8702124ebeaec028b9511b23..e5b8e92e8002289431a9f783fd4e2cf9cd27953d 100644 (file)
@@ -150,13 +150,15 @@ int fdset_remove(FDSet *s, int fd) {
 int fdset_new_fill(
                 int filter_cloexec, /* if < 0 takes all fds, otherwise only those with O_CLOEXEC set (1) or unset (0) */
                 FDSet **ret) {
+
         _cleanup_(fdset_shallow_freep) FDSet *s = NULL;
         _cleanup_closedir_ DIR *d = NULL;
         int r;
 
         assert(ret);
 
-        /* Creates an fdset and fills in all currently open file descriptors. */
+        /* Creates an fdset and fills in all currently open file descriptors. Also set all collected fds
+         * to CLOEXEC. */
 
         d = opendir("/proc/self/fd");
         if (!d) {
@@ -191,6 +193,7 @@ int fdset_new_fill(
                         /* If user asked for that filter by O_CLOEXEC. This is useful so that fds that have
                          * been passed in can be collected and fds which have been created locally can be
                          * ignored, under the assumption that only the latter have O_CLOEXEC set. */
+
                         fl = fcntl(fd, F_GETFD);
                         if (fl < 0)
                                 return -errno;
@@ -199,6 +202,13 @@ int fdset_new_fill(
                                 continue;
                 }
 
+                /* We need to set CLOEXEC manually only if we're collecting non-CLOEXEC fds. */
+                if (filter_cloexec <= 0) {
+                        r = fd_cloexec(fd, true);
+                        if (r < 0)
+                                return r;
+                }
+
                 r = fdset_put(s, fd);
                 if (r < 0)
                         return r;
index 8947a319b62f5ffcdbf178a23695d603587b41de..8f00e598fdd676728843bac01c488e1be80a7fa8 100644 (file)
@@ -11,8 +11,8 @@
 #include "tmpfile-util.h"
 
 TEST(fdset_new_fill) {
-        int fd = -EBADF;
         _cleanup_fdset_free_ FDSet *fdset = NULL;
+        int fd = -EBADF, flags;
 
         log_close();
         log_set_open_when_needed(true);
@@ -50,6 +50,9 @@ TEST(fdset_new_fill) {
 
         assert_se(fdset_new_fill(/* filter_cloexec= */ 0, &fdset) >= 0);
         assert_se(fdset_contains(fdset, fd));
+        flags = fcntl(fd, F_GETFD);
+        assert_se(flags >= 0);
+        assert_se(FLAGS_SET(flags, FD_CLOEXEC));
         fdset = fdset_free(fdset);
         assert_se(fcntl(fd, F_GETFD) < 0);
         assert_se(errno == EBADF);