diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2022-06-02 00:25:59 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2022-06-02 00:25:59 -0700 |
commit | d33197ad59f19fe8a22859027b7f49f41799d0d1 (patch) | |
tree | eb5a32590a8f86a2032273e64599423911fab48f | |
parent | 21a61f5e25528364ddbd2e5abdbca66b5986ea77 (diff) | |
parent | e086d3770c12f4e98ac3fdbbcf8ece40b26c8746 (diff) |
Merge e086d3770c12f4e98ac3fdbbcf8ece40b26c8746 on remote branch
Change-Id: If556ab5fcaa0049224283e5995b61a738a2b54fa
-rw-r--r-- | libc/SECCOMP_ALLOWLIST_COMMON.TXT | 4 | ||||
-rw-r--r-- | libc/bionic/spawn.cpp | 31 | ||||
-rw-r--r-- | libc/include/spawn.h | 2 | ||||
-rw-r--r-- | tests/gwp_asan_test.cpp | 2 |
4 files changed, 37 insertions, 2 deletions
diff --git a/libc/SECCOMP_ALLOWLIST_COMMON.TXT b/libc/SECCOMP_ALLOWLIST_COMMON.TXT index 6650d7e32..0366fdf0f 100644 --- a/libc/SECCOMP_ALLOWLIST_COMMON.TXT +++ b/libc/SECCOMP_ALLOWLIST_COMMON.TXT @@ -31,6 +31,8 @@ int seccomp:seccomp(unsigned int operation, unsigned int flags, void *args) all int open:open(const char*, int, ...) arm,x86,x86_64 int stat64:stat64(const char*, struct stat64*) arm,x86 ssize_t readlink:readlink(const char*, char*, size_t) arm,x86,x86_64 +# Needed by ubsan in T? (http://b/229989971) +int stat(const char*, struct stat*) arm,x86,x86_64 # # Useful new syscalls which we don't yet use in bionic. @@ -74,3 +76,5 @@ int futex_time64(int*, int, int, const timespec64*, int*, int) lp32 int sched_rr_get_interval_time64(pid_t, timespec64*) lp32 # Since Linux 5.4, not in glibc. Probed for and conditionally used by ART. int userfaultfd(int) all +# Since Linux 5.9, used by POSIX_SPAWN_CLOEXEC_DEFAULT +int close_range(unsigned int, unsigned int, int) all diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp index 2067a1a92..59f763138 100644 --- a/libc/bionic/spawn.cpp +++ b/libc/bionic/spawn.cpp @@ -30,9 +30,12 @@ #include <errno.h> #include <fcntl.h> +#include <linux/close_range.h> #include <signal.h> #include <stdlib.h> #include <string.h> +#include <sys/resource.h> +#include <sys/syscall.h> #include <unistd.h> #include <android/fdsan.h> @@ -40,6 +43,28 @@ #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() { + // requires 5.11+ or ACK 5.10-T kernel, otherwise returns ENOSYS or EINVAL + if (!syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC)) return 0; + + // 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 +166,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 +228,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; diff --git a/tests/gwp_asan_test.cpp b/tests/gwp_asan_test.cpp index b442f51e6..b2c7780b1 100644 --- a/tests/gwp_asan_test.cpp +++ b/tests/gwp_asan_test.cpp @@ -43,7 +43,7 @@ void RunGwpAsanTest(const char* test_name) { std::string filter_arg = "--gtest_filter="; filter_arg += test_name; std::string exec(testing::internal::GetArgvs()[0]); - eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str()}); + eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr}); eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); }, /* expected_exit_status */ 0, // |expected_output_regex|, ensure at least one test ran: |