Merge "Revert "Reland: Soft-enable MAC address restrictions with allowlist.""
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 043510c..48e8674 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -137,14 +137,6 @@
return;
}
- // Lots of code will (sensibly) fork, call close on all of their fds,
- // and then exec. Compare our cached pid value against the real one to detect
- // this scenario and permit it.
- pid_t cached_pid = __get_cached_pid();
- if (cached_pid == 0 || cached_pid != syscall(__NR_getpid)) {
- return;
- }
-
struct {
size_t size;
char buf[512];
diff --git a/libc/bionic/fdtrack.cpp b/libc/bionic/fdtrack.cpp
index 1123512..89a208f 100644
--- a/libc/bionic/fdtrack.cpp
+++ b/libc/bionic/fdtrack.cpp
@@ -37,8 +37,14 @@
_Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+bool __android_fdtrack_globally_disabled = false;
+
+void android_fdtrack_set_globally_enabled(bool new_value) {
+ __android_fdtrack_globally_disabled = !new_value;
+}
+
bool android_fdtrack_get_enabled() {
- return !__get_bionic_tls().fdtrack_disabled;
+ return !__get_bionic_tls().fdtrack_disabled && !__android_fdtrack_globally_disabled;
}
bool android_fdtrack_set_enabled(bool new_value) {
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 8c5cf2b..d432c6d 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,6 +31,7 @@
#include <android/fdsan.h>
#include "private/bionic_defs.h"
+#include "private/bionic_fdtrack.h"
#include "pthread_internal.h"
__BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE
@@ -55,9 +56,10 @@
int result = __clone_for_fork();
if (result == 0) {
- // Disable fdsan post-fork, so we don't falsely trigger on processes that
+ // Disable fdsan and fdtrack post-fork, so we don't falsely trigger on processes that
// fork, close all of their fds, and then exec.
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+ android_fdtrack_set_globally_enabled(false);
// Reset the stack_and_tls VMA name so it doesn't end with a tid from the
// parent process.
diff --git a/libc/dns/resolv/res_data.c b/libc/dns/resolv/res_data.c
index 9bc02e7..4f8df69 100644
--- a/libc/dns/resolv/res_data.c
+++ b/libc/dns/resolv/res_data.c
@@ -40,6 +40,7 @@
#include <ctype.h>
#include <netdb.h>
#include "resolv_private.h"
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -82,11 +83,9 @@
int res_ourserver_p(const res_state, const struct sockaddr *);
-#define res_need_init() ((_nres.options & RES_INIT) == 0U)
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-int
-res_init(void) {
- int rv;
+static void init_once(void) {
extern int __res_vinit(res_state, int);
#ifdef COMPAT__RES
/*
@@ -140,11 +139,21 @@
if (!_nres.id)
_nres.id = res_randomid();
- rv = __res_vinit(&_nres, 1);
+ __res_vinit(&_nres, 1);
#ifdef COMPAT__RES
__res_put_old_state(&_nres);
#endif
- return rv;
+}
+
+int
+res_init(void) {
+ pthread_once(&once_control, init_once);
+ return 0;
+}
+
+static res_state get_static_res_state() {
+ pthread_once(&once_control, init_once);
+ return &_nres;
}
void
@@ -159,10 +168,7 @@
void
fp_nquery(const u_char *msg, int len, FILE *file) {
- if (res_need_init() && res_init() == -1)
- return;
-
- res_pquery(&_nres, msg, len, file);
+ res_pquery(get_static_res_state(), msg, len, file);
}
int
@@ -175,11 +181,7 @@
u_char *buf, /* buffer to put query */
int buflen) /* size of buffer */
{
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
- return (res_nmkquery(&_nres, op, dname, class, type,
+ return (res_nmkquery(get_static_res_state(), op, dname, class, type,
data, datalen,
newrr_in, buf, buflen));
}
@@ -187,12 +189,7 @@
#ifdef _LIBRESOLV
int
res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nmkupdate(&_nres, rrecp_in, buf, buflen));
+ return (res_nmkupdate(get_static_res_state(), rrecp_in, buf, buflen));
}
#endif
@@ -202,11 +199,7 @@
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer buffer */
{
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
- return (res_nquery(&_nres, name, class, type, answer, anslen));
+ return (res_nquery(get_static_res_state(), name, class, type, answer, anslen));
}
void
@@ -226,12 +219,7 @@
int
res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
- if (res_need_init() && res_init() == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
-
- return (res_nsend(&_nres, buf, buflen, ans, anssiz));
+ return (res_nsend(get_static_res_state(), buf, buflen, ans, anssiz));
}
#ifdef _LIBRESOLV
@@ -239,12 +227,7 @@
res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
u_char *ans, int anssiz)
{
- if (res_need_init() && res_init() == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
-
- return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz));
+ return (res_nsendsigned(get_static_res_state(), buf, buflen, key, ans, anssiz));
}
#endif
@@ -256,12 +239,7 @@
#ifdef _LIBRESOLV
int
res_update(ns_updrec *rrecp_in) {
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nupdate(&_nres, rrecp_in, NULL));
+ return (res_nupdate(get_static_res_state(), rrecp_in, NULL));
}
#endif
@@ -271,12 +249,7 @@
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nsearch(&_nres, name, class, type, answer, anslen));
+ return (res_nsearch(get_static_res_state(), name, class, type, answer, anslen));
}
int
@@ -286,12 +259,7 @@
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- if (res_need_init() && res_init() == -1) {
- RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nquerydomain(&_nres, name, domain,
+ return (res_nquerydomain(get_static_res_state(), name, domain,
class, type,
answer, anslen));
}
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 51a1076..c31e306 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1772,6 +1772,7 @@
android_fdtrack_compare_exchange_hook; # llndk
android_fdtrack_get_enabled; # llndk
android_fdtrack_set_enabled; # llndk
+ android_fdtrack_set_globally_enabled; # llndk
android_net_res_stats_get_info_for_net;
android_net_res_stats_aggregate;
android_net_res_stats_get_usable_servers;
diff --git a/libc/platform/bionic/fdtrack.h b/libc/platform/bionic/fdtrack.h
index 6eb379b..fe6ca84 100644
--- a/libc/platform/bionic/fdtrack.h
+++ b/libc/platform/bionic/fdtrack.h
@@ -70,4 +70,8 @@
bool android_fdtrack_get_enabled() __INTRODUCED_IN(30);
bool android_fdtrack_set_enabled(bool new_value) __INTRODUCED_IN(30);
+// Globally enable/disable fdtrack.
+// This is primaryily useful to reenable fdtrack after it's been automatically disabled post-fork.
+void android_fdtrack_set_globally_enabled(bool new_value) __INTRODUCED_IN(31);
+
__END_DECLS
diff --git a/libc/private/bionic_fdtrack.h b/libc/private/bionic_fdtrack.h
index 259897c..c05b32b 100644
--- a/libc/private/bionic_fdtrack.h
+++ b/libc/private/bionic_fdtrack.h
@@ -28,41 +28,43 @@
#pragma once
-#include <sys/cdefs.h>
#include <stdatomic.h>
+#include <sys/cdefs.h>
#include "platform/bionic/fdtrack.h"
#include "bionic/pthread_internal.h"
-#include "private/bionic_tls.h"
#include "private/ErrnoRestorer.h"
+#include "private/bionic_tls.h"
extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+extern "C" bool __android_fdtrack_globally_disabled;
// Macro to record file descriptor creation.
// e.g.:
// int socket(int domain, int type, int protocol) {
// return FDTRACK_CREATE_NAME("socket", __socket(domain, type, protocol));
// }
-#define FDTRACK_CREATE_NAME(name, fd_value) \
- ({ \
- int __fd = (fd_value); \
- if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
- !__predict_false(__get_thread()->is_vforked())) { \
- bionic_tls& tls = __get_bionic_tls(); \
- /* fdtrack_disabled is only true during reentrant calls. */ \
- if (!__predict_false(tls.fdtrack_disabled)) { \
- ErrnoRestorer r; \
- tls.fdtrack_disabled = true; \
- android_fdtrack_event event; \
- event.fd = __fd; \
- event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE; \
- event.data.create.function_name = name; \
- atomic_load(&__android_fdtrack_hook)(&event); \
- tls.fdtrack_disabled = false; \
- } \
- } \
- __fd; \
+#define FDTRACK_CREATE_NAME(name, fd_value) \
+ ({ \
+ int __fd = (fd_value); \
+ if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
+ !__predict_false(__get_thread()->is_vforked())) { \
+ bionic_tls& tls = __get_bionic_tls(); \
+ /* fdtrack_disabled is only true during reentrant calls. */ \
+ if (!__predict_false(tls.fdtrack_disabled) && \
+ !__predict_false(__android_fdtrack_globally_disabled)) { \
+ ErrnoRestorer r; \
+ tls.fdtrack_disabled = true; \
+ android_fdtrack_event event; \
+ event.fd = __fd; \
+ event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE; \
+ event.data.create.function_name = name; \
+ atomic_load (&__android_fdtrack_hook)(&event); \
+ tls.fdtrack_disabled = false; \
+ } \
+ } \
+ __fd; \
})
// Macro to record file descriptor creation, with the current function's name.
@@ -74,22 +76,23 @@
// Macro to record file descriptor closure.
// Note that this does not actually close the file descriptor.
-#define FDTRACK_CLOSE(fd_value) \
- ({ \
- int __fd = (fd_value); \
- if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
- !__predict_false(__get_thread()->is_vforked())) { \
- bionic_tls& tls = __get_bionic_tls(); \
- if (!__predict_false(tls.fdtrack_disabled)) { \
- int saved_errno = errno; \
- tls.fdtrack_disabled = true; \
- android_fdtrack_event event; \
- event.fd = __fd; \
- event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE; \
- atomic_load(&__android_fdtrack_hook)(&event); \
- tls.fdtrack_disabled = false; \
- errno = saved_errno; \
- } \
- } \
- __fd; \
+#define FDTRACK_CLOSE(fd_value) \
+ ({ \
+ int __fd = (fd_value); \
+ if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
+ !__predict_false(__get_thread()->is_vforked())) { \
+ bionic_tls& tls = __get_bionic_tls(); \
+ if (!__predict_false(tls.fdtrack_disabled) && \
+ !__predict_false(__android_fdtrack_globally_disabled)) { \
+ int saved_errno = errno; \
+ tls.fdtrack_disabled = true; \
+ android_fdtrack_event event; \
+ event.fd = __fd; \
+ event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE; \
+ atomic_load (&__android_fdtrack_hook)(&event); \
+ tls.fdtrack_disabled = false; \
+ errno = saved_errno; \
+ } \
+ } \
+ __fd; \
})
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp
index fd56274..2e9cfbc 100644
--- a/libfdtrack/fdtrack.cpp
+++ b/libfdtrack/fdtrack.cpp
@@ -93,6 +93,8 @@
android_fdtrack_hook_t expected = nullptr;
installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook);
}
+
+ android_fdtrack_set_globally_enabled(true);
}
__attribute__((destructor)) static void dtor() {
diff --git a/tests/fdtrack_test.cpp b/tests/fdtrack_test.cpp
index 13f1b2e..9fcb402 100644
--- a/tests/fdtrack_test.cpp
+++ b/tests/fdtrack_test.cpp
@@ -57,8 +57,13 @@
}
}
-std::vector<android_fdtrack_event> FdtrackRun(void (*func)()) {
+std::vector<android_fdtrack_event> FdtrackRun(void (*func)(), bool reenable = true) {
// Each bionic test is run in separate process, so we can safely use a static here.
+ // However, since they're all forked, we need to reenable fdtrack.
+ if (reenable) {
+ android_fdtrack_set_globally_enabled(true);
+ }
+
static std::vector<android_fdtrack_event> events;
events.clear();
@@ -129,6 +134,21 @@
#endif
}
+TEST(fdtrack, fork) {
+#if defined(__BIONIC__)
+ ASSERT_EXIT(
+ []() {
+ static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
+ ASSERT_NE(-1, fd);
+
+ auto events = FdtrackRun([]() { close(fd); }, false);
+ ASSERT_EQ(0U, events.size());
+ exit(0);
+ }(),
+ testing::ExitedWithCode(0), "");
+#endif
+}
+
TEST(fdtrack, enable_disable) {
#if defined(__BIONIC__)
static int fd1 = -1;
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 7c2c890..16299cc 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -851,11 +851,15 @@
}
TEST(time, clock) {
- // clock(3) is hard to test, but a 1s sleep should cost less than 20ms.
+ // clock(3) is hard to test, but a 1s sleep should cost less than 10ms on average.
+ static const clock_t N = 5;
+ static const clock_t mean_limit_ms = 10;
clock_t t0 = clock();
- sleep(1);
+ for (size_t i = 0; i < N; ++i) {
+ sleep(1);
+ }
clock_t t1 = clock();
- ASSERT_LT(t1 - t0, 20 * (CLOCKS_PER_SEC / 1000));
+ ASSERT_LT(t1 - t0, N * mean_limit_ms * (CLOCKS_PER_SEC / 1000));
}
static pid_t GetInvalidPid() {