Merge "Call __libc_init_malloc from scudo."
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 1f099cf..b6a9ed2 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -101,13 +101,15 @@
__libc_add_main_thread();
- // Register atfork handlers to take and release the arc4random lock.
- pthread_atfork(arc4random_fork_handler, _thread_arc4_unlock, _thread_arc4_unlock);
-
__system_properties_init(); // Requires 'environ'.
__libc_init_fdsan(); // Requires system properties (for debug.fdsan).
}
+void __libc_init_fork_handler() {
+ // Register atfork handlers to take and release the arc4random lock.
+ pthread_atfork(arc4random_fork_handler, _thread_arc4_unlock, _thread_arc4_unlock);
+}
+
__noreturn static void __early_abort(int line) {
// We can't write to stdout or stderr because we're aborting before we've checked that
// it's safe for us to use those file descriptors. We probably can't strace either, so
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 73f5817..0c2e78a 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -56,4 +56,8 @@
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
+// The fork handler must be initialised after __libc_init_malloc, as
+// pthread_atfork may call malloc() during its once-init.
+__LIBC_HIDDEN__ void __libc_init_fork_handler();
+
#endif
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index d6d5552..ca94652 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -99,6 +99,8 @@
// Hooks for various libraries to let them know that we're starting up.
__libc_globals.mutate(__libc_init_malloc);
+ __libc_init_fork_handler();
+
#if __has_feature(hwaddress_sanitizer)
// Notify the HWASan runtime library whenever a library is loaded or unloaded
// so that it can update its shadow memory.
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 28c0b0c..5c1d27e 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -181,6 +181,7 @@
layout_static_tls(args);
__libc_init_main_thread_final();
__libc_init_common();
+ __libc_init_fork_handler();
call_ifunc_resolvers();
apply_gnu_relro();
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 2b3200c..dd6b129 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -52,16 +52,31 @@
// Things we actually have to calculate...
//
case _SC_ARG_MAX:
- // https://lkml.org/lkml/2017/11/15/813...
+ // You might think that just returning a constant 128KiB (ARG_MAX) would
+ // make sense, as this guy did:
//
- // I suspect a 128kB sysconf(_SC_ARG_MAX) is the sanest bet, simply
- // because of that "conservative is better than aggressive".
+ // https://lkml.org/lkml/2017/11/15/813...
//
- // Especially since _technically_ we're still limiting things to that
- // 128kB due to the single-string limit.
+ // I suspect a 128kB sysconf(_SC_ARG_MAX) is the sanest bet, simply
+ // because of that "conservative is better than aggressive".
//
- // Linus
- return ARG_MAX;
+ // Especially since _technically_ we're still limiting things to that
+ // 128kB due to the single-string limit.
+ //
+ // Linus
+ //
+ // In practice that caused us trouble with toybox tests for xargs edge
+ // cases. The tests assume that they can at least reach the kernel's
+ // "minimum maximum" of 128KiB, but if we report 128KiB for _SC_ARG_MAX
+ // and xargs starts subtracting the environment space and so on from that,
+ // then xargs will think it's run out of space when given 128KiB of data,
+ // which should always work. See this thread for more:
+ //
+ // http://lists.landley.net/pipermail/toybox-landley.net/2019-November/011229.html
+ //
+ // So let's resign ourselves to tracking what the kernel actually does.
+ // Right now (2019, Linux 5.3) that amounts to:
+ return MAX(MIN(__sysconf_rlimit(RLIMIT_STACK) / 4, 3 * _STK_LIM / 4), ARG_MAX);
case _SC_AVPHYS_PAGES: return get_avphys_pages();
case _SC_CHILD_MAX: return __sysconf_rlimit(RLIMIT_NPROC);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 99d92e6..f3b08c3 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -27,6 +27,7 @@
#include <stdint.h>
#include <sys/capability.h>
#include <sys/param.h>
+#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/utsname.h>
@@ -1065,11 +1066,38 @@
}
TEST(UNISTD_TEST, sysconf_SC_ARG_MAX) {
- // https://lkml.org/lkml/2017/11/15/813.
-#if !defined(ARG_MAX)
-#define ARG_MAX 131072
-#endif
- ASSERT_EQ(ARG_MAX, sysconf(_SC_ARG_MAX));
+ // Since Linux 2.6.23, ARG_MAX isn't a constant and depends on RLIMIT_STACK.
+ // See prepare_arg_pages() in the kernel for the gory details:
+ // https://elixir.bootlin.com/linux/v5.3.11/source/fs/exec.c#L451
+
+ // Get our current limit, and set things up so we restore the limit.
+ rlimit rl;
+ ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
+ uint64_t original_rlim_cur = rl.rlim_cur;
+ if (rl.rlim_cur == RLIM_INFINITY) {
+ rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
+ }
+ auto guard = android::base::make_scope_guard([&rl, original_rlim_cur]() {
+ rl.rlim_cur = original_rlim_cur;
+ ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+ });
+
+ // _SC_ARG_MAX should be 1/4 the stack size.
+ EXPECT_EQ(static_cast<long>(rl.rlim_cur / 4), sysconf(_SC_ARG_MAX));
+
+ // If you have a really small stack, the kernel still guarantees "32 pages" (see fs/exec.c).
+ rl.rlim_cur = 1024;
+ rl.rlim_max = RLIM_INFINITY;
+ ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+ EXPECT_EQ(static_cast<long>(32 * sysconf(_SC_PAGE_SIZE)), sysconf(_SC_ARG_MAX));
+
+ // With a 128-page stack limit, we know exactly what _SC_ARG_MAX should be...
+ rl.rlim_cur = 128 * sysconf(_SC_PAGE_SIZE);
+ rl.rlim_max = RLIM_INFINITY;
+ ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+ EXPECT_EQ(static_cast<long>((128 * sysconf(_SC_PAGE_SIZE)) / 4), sysconf(_SC_ARG_MAX));
}
TEST(UNISTD_TEST, sysconf_unknown) {