aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-21 12:29:50 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-21 12:29:50 +0000
commite6be9ec821527701f67a94367b5e46c022c807aa (patch)
tree0425e2528abca3f7f9af7b664013837d0dd37320
parent2842b1ff2d62984b963384da0a5fb66cfcfaecf7 (diff)
parentbbe7c690f1fbe714fe06c2107cb3e4d25bc791f2 (diff)
downloadbionic-android13-mainline-go-adservices-release.tar.gz
Snap for 8626064 from bbe7c690f1fbe714fe06c2107cb3e4d25bc791f2 to mainline-go-adservices-releaseaml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000android13-mainline-go-adservices-release
Change-Id: I7b085a1bacc56d8cdc2b1302d818e50a5eead597
-rw-r--r--libc/SECCOMP_ALLOWLIST_COMMON.TXT4
-rw-r--r--libc/bionic/spawn.cpp31
-rw-r--r--libc/include/spawn.h2
-rw-r--r--tests/gwp_asan_test.cpp2
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: