aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Żenczykowski <maze@google.com>2022-04-27 18:19:18 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-27 18:19:18 +0000
commita5d42df66a5f2f907254191fc4ec48c48551cf33 (patch)
tree1f1ede0fd6d7ace7113ccacb36b265d5d8415f4b
parente3cf35269f2386d620b111468c4cacf5866c3633 (diff)
parent06b249fc75b4f554b52198b94737a5aabe30ddb0 (diff)
downloadbionic-a5d42df66a5f2f907254191fc4ec48c48551cf33.tar.gz
posix_spawn - implement support for POSIX_SPAWN_CLOEXEC_DEFAULT am: 06b249fc75
Original change: https://googleplex-android-review.googlesource.com/c/platform/bionic/+/17951150 Change-Id: I7c9670ff2045aeb9507c42360870077e1dc3f023 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libc/bionic/spawn.cpp26
-rw-r--r--libc/include/spawn.h2
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;