diff options
author | Maciej Żenczykowski <maze@google.com> | 2022-04-27 01:12:04 +0000 |
---|---|---|
committer | Nucca Chen <nuccachen@google.com> | 2022-04-27 11:03:08 +0000 |
commit | 06b249fc75b4f554b52198b94737a5aabe30ddb0 (patch) | |
tree | 1f1ede0fd6d7ace7113ccacb36b265d5d8415f4b | |
parent | 917f161854c5a4e8e62b88fb778a8f2a943f3423 (diff) | |
download | bionic-06b249fc75b4f554b52198b94737a5aabe30ddb0.tar.gz |
posix_spawn - implement support for POSIX_SPAWN_CLOEXEC_DEFAULT
This new posix_spawn attribute flag marks all file descriptors
(except stdin/out/err) as close-on-exec before executing any user
registered file actions (posix_spawn_file_actions_addopen/adddup2).
Test: TreeHugger
Bug: 229913920
Original change: https://android-review.googlesource.com/c/platform/bionic/+/1955269
Merged-In: If458100d6a253a9b0348d4e93a9a610225f89615
Change-Id: If458100d6a253a9b0348d4e93a9a610225f89615
Signed-off-by: Maciej Żenczykowski <maze@google.com>
(cherry picked from commit fb66c0c345f17d740b6a2ef7755f768dd5bd96ee)
-rw-r--r-- | libc/bionic/spawn.cpp | 26 | ||||
-rw-r--r-- | libc/include/spawn.h | 2 |
2 files changed, 27 insertions, 1 deletions
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp index 2067a1a92..314a05669 100644 --- a/libc/bionic/spawn.cpp +++ b/libc/bionic/spawn.cpp @@ -33,6 +33,7 @@ #include <signal.h> #include <stdlib.h> #include <string.h> +#include <sys/resource.h> #include <unistd.h> #include <android/fdsan.h> @@ -40,6 +41,25 @@ #include "private/ScopedSignalBlocker.h" #include "private/SigSetConverter.h" +static int set_cloexec(int i) { + int v = fcntl(i, F_GETFD); + if (v == -1) return -1; // almost certainly: errno == EBADF + return fcntl(i, F_SETFD, v | FD_CLOEXEC); +} + +// mark all open fds except stdin/out/err as close-on-exec +static int cloexec_except_stdioe() { + // unfortunately getrlimit can lie: + // - both soft and hard limits can be lowered to 0, with fds still open, so it can underestimate + // - in practice it usually is some really large value (like 32K or more) + // even though only a handful of small fds are actually open (ie. < 500), + // this results in poor performance when trying to act on all possibly open fds + struct rlimit m; + int max = getrlimit(RLIMIT_NOFILE, &m) ? 1000000 : m.rlim_max; + for (int i = 3; i < max; ++i) set_cloexec(i); + return 0; +} + enum Action { kOpen, kClose, @@ -141,6 +161,10 @@ static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) { if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) { if (sigprocmask64(SIG_SETMASK, &(*attr)->sigmask.sigset64, nullptr)) _exit(127); } + + if ((flags & POSIX_SPAWN_CLOEXEC_DEFAULT) != 0) { + if (cloexec_except_stdioe()) _exit(127); + } } static int posix_spawn(pid_t* pid_ptr, @@ -199,7 +223,7 @@ int posix_spawnattr_destroy(posix_spawnattr_t* attr) { int posix_spawnattr_setflags(posix_spawnattr_t* attr, short flags) { if ((flags & ~(POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER | - POSIX_SPAWN_USEVFORK | POSIX_SPAWN_SETSID)) != 0) { + POSIX_SPAWN_USEVFORK | POSIX_SPAWN_SETSID | POSIX_SPAWN_CLOEXEC_DEFAULT)) != 0) { return EINVAL; } (*attr)->flags = flags; diff --git a/libc/include/spawn.h b/libc/include/spawn.h index 2e239bfc2..e4454530e 100644 --- a/libc/include/spawn.h +++ b/libc/include/spawn.h @@ -46,6 +46,8 @@ __BEGIN_DECLS #define POSIX_SPAWN_USEVFORK 64 #define POSIX_SPAWN_SETSID 128 #endif +// mark all fds (except stdin/out/err) as close-on-exec prior to executing registered file actions +#define POSIX_SPAWN_CLOEXEC_DEFAULT 256 typedef struct __posix_spawnattr* posix_spawnattr_t; typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t; |