From: Mike Yuan Date: Thu, 30 Nov 2023 16:00:27 +0000 (+0800) Subject: fdset: set all collected fds to CLOEXEC in fdset_new_fill() X-Git-Tag: v256-rc1~1568^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2467ea894b37b0861b92e35edd93788f8e2a342;p=thirdparty%2Fsystemd.git fdset: set all collected fds to CLOEXEC in fdset_new_fill() --- diff --git a/src/core/main.c b/src/core/main.c index 2ac59dabf5a..3f71cc09479 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -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))); diff --git a/src/notify/notify.c b/src/notify/notify.c index 675fbda752a..f63ec8b355f 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -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) { diff --git a/src/shared/fdset.c b/src/shared/fdset.c index b62f15c6494..e5b8e92e800 100644 --- a/src/shared/fdset.c +++ b/src/shared/fdset.c @@ -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; diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c index 8947a319b62..8f00e598fdd 100644 --- a/src/test/test-fdset.c +++ b/src/test/test-fdset.c @@ -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);