diff options
-rw-r--r-- | libc/bionic/android_set_abort_message.cpp | 16 | ||||
-rw-r--r-- | libc/bionic/fdsan.cpp | 40 | ||||
-rw-r--r-- | libc/bionic/libc_init_common.cpp | 20 | ||||
-rw-r--r-- | libc/bionic/libc_init_common.h | 4 | ||||
-rw-r--r-- | libc/bionic/libc_init_dynamic.cpp | 13 | ||||
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 16 | ||||
-rw-r--r-- | libc/private/KernelArgumentBlock.h | 7 | ||||
-rw-r--r-- | libc/private/bionic_globals.h | 13 | ||||
-rw-r--r-- | linker/dlfcn.cpp | 6 | ||||
-rw-r--r-- | linker/ld_android.cpp | 1 | ||||
-rw-r--r-- | linker/linker.arm.map | 1 | ||||
-rw-r--r-- | linker/linker.generic.map | 1 | ||||
-rw-r--r-- | linker/linker_main.cpp | 19 | ||||
-rw-r--r-- | tests/dl_test.cpp | 2 | ||||
-rw-r--r-- | tests/libs/exec_linker_helper.cpp | 4 |
15 files changed, 71 insertions, 92 deletions
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp index 58f24cfa8..56e67710a 100644 --- a/libc/bionic/android_set_abort_message.cpp +++ b/libc/bionic/android_set_abort_message.cpp @@ -35,10 +35,9 @@ #include <sys/mman.h> #include "private/bionic_defs.h" +#include "private/bionic_globals.h" #include "private/ScopedPthreadMutexLocker.h" -static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER; - struct abort_msg_t { size_t size; char msg[0]; @@ -56,8 +55,6 @@ static_assert(offsetof(magic_abort_msg_t, msg) == 2 * sizeof(uint64_t), "The in-memory layout of magic_abort_msg_t is not consistent with what automated " "tools expect."); -abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. - [[clang::optnone]] static void fill_abort_message_magic(magic_abort_msg_t* new_magic_abort_message) { // 128-bit magic for the abort message. Chosen by fair dice roll. @@ -71,14 +68,9 @@ static void fill_abort_message_magic(magic_abort_msg_t* new_magic_abort_message) __BIONIC_WEAK_FOR_NATIVE_BRIDGE void android_set_abort_message(const char* msg) { - ScopedPthreadMutexLocker locker(&g_abort_msg_lock); - - if (__abort_message_ptr == nullptr) { - // We must have crashed _very_ early. - return; - } + ScopedPthreadMutexLocker locker(&__libc_shared_globals()->abort_msg_lock); - if (*__abort_message_ptr != nullptr) { + if (__libc_shared_globals()->abort_msg != nullptr) { // We already have an abort message. // Assume that the first crash is the one most worth reporting. return; @@ -94,5 +86,5 @@ void android_set_abort_message(const char* msg) { fill_abort_message_magic(new_magic_abort_message); new_magic_abort_message->msg.size = size; strcpy(new_magic_abort_message->msg.msg, msg); - *__abort_message_ptr = &new_magic_abort_message->msg; + __libc_shared_globals()->abort_msg = &new_magic_abort_message->msg; } diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp index 9a9fee272..6440ae059 100644 --- a/libc/bionic/fdsan.cpp +++ b/libc/bionic/fdsan.cpp @@ -132,17 +132,13 @@ void __libc_init_fdsan() { nullptr); } -static FdTable* GetFdTable() { - if (!__libc_shared_globals) { - return nullptr; - } - - return &__libc_shared_globals->fd_table; +static FdTable& GetFdTable() { + return __libc_shared_globals()->fd_table; } // Exposed to the platform to allow crash_dump to print out the fd table. extern "C" void* android_fdsan_get_fd_table() { - return GetFdTable(); + return &GetFdTable(); } static FdEntry* GetFdEntry(int fd) { @@ -150,21 +146,13 @@ static FdEntry* GetFdEntry(int fd) { return nullptr; } - auto* fd_table = GetFdTable(); - if (!fd_table) { - return nullptr; - } - - return fd_table->at(fd); + return GetFdTable().at(fd); } __printflike(1, 0) static void fdsan_error(const char* fmt, ...) { - auto* fd_table = GetFdTable(); - if (!fd_table) { - return; - } + auto& fd_table = GetFdTable(); - auto error_level = atomic_load(&fd_table->error_level); + auto error_level = atomic_load(&fd_table.error_level); if (error_level == ANDROID_FDSAN_ERROR_LEVEL_DISABLED) { return; } @@ -198,7 +186,7 @@ __printflike(1, 0) static void fdsan_error(const char* fmt, ...) { switch (error_level) { case ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE: - atomic_compare_exchange_strong(&fd_table->error_level, &error_level, + atomic_compare_exchange_strong(&fd_table.error_level, &error_level, ANDROID_FDSAN_ERROR_LEVEL_DISABLED); __BIONIC_FALLTHROUGH; case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS: @@ -360,21 +348,11 @@ void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t ne } android_fdsan_error_level android_fdsan_get_error_level() { - auto* fd_table = GetFdTable(); - if (!fd_table) { - async_safe_fatal("attempted to get fdsan error level before libc initialization?"); - } - - return fd_table->error_level; + return GetFdTable().error_level; } android_fdsan_error_level android_fdsan_set_error_level(android_fdsan_error_level new_level) { - auto* fd_table = GetFdTable(); - if (!fd_table) { - async_safe_fatal("attempted to get fdsan error level before libc initialization?"); - } - - return atomic_exchange(&fd_table->error_level, new_level); + return atomic_exchange(&GetFdTable().error_level, new_level); } int close(int fd) { diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp index a860b98dd..4702e1c9a 100644 --- a/libc/bionic/libc_init_common.cpp +++ b/libc/bionic/libc_init_common.cpp @@ -52,11 +52,9 @@ #include "private/thread_private.h" #include "pthread_internal.h" -extern "C" abort_msg_t** __abort_message_ptr; extern "C" int __system_properties_init(void); __LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals; -__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals; // Not public, but well-known in the BSDs. const char* __progname; @@ -72,9 +70,6 @@ void __libc_init_globals(KernelArgumentBlock& args) { }); } -void __libc_init_shared_globals(libc_shared_globals*) { -} - #if !defined(__LP64__) static void __check_max_thread_id() { if (gettid() > 65535) { @@ -96,12 +91,11 @@ void __libc_add_main_thread() { __pthread_internal_add(main_thread); } -void __libc_init_common(KernelArgumentBlock& args) { +void __libc_init_common() { // Initialize various globals. - environ = args.envp; + environ = __libc_shared_globals()->init_environ; errno = 0; - __progname = args.argv[0] ? args.argv[0] : "<unknown>"; - __abort_message_ptr = args.abort_message_ptr; + __progname = __libc_shared_globals()->init_progname ?: "<unknown>"; #if !defined(__LP64__) __check_max_thread_id(); @@ -300,9 +294,7 @@ static void __initialize_personality() { #endif } -void __libc_init_AT_SECURE(KernelArgumentBlock& args) { - __abort_message_ptr = args.abort_message_ptr; - +void __libc_init_AT_SECURE(char** env) { // Check that the kernel provided a value for AT_SECURE. errno = 0; unsigned long is_AT_SECURE = getauxval(AT_SECURE); @@ -313,11 +305,11 @@ void __libc_init_AT_SECURE(KernelArgumentBlock& args) { // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc __nullify_closed_stdio(); - __sanitize_environment_variables(args.envp); + __sanitize_environment_variables(env); } // Now the environment has been sanitized, make it available. - environ = args.envp; + environ = __libc_shared_globals()->init_environ = env; __initialize_personality(); } diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h index 6ce4d10ef..84b59ca2d 100644 --- a/libc/bionic/libc_init_common.h +++ b/libc/bionic/libc_init_common.h @@ -54,8 +54,8 @@ class KernelArgumentBlock; __LIBC_HIDDEN__ void __libc_init_globals(KernelArgumentBlock& args); -__LIBC_HIDDEN__ void __libc_init_common(KernelArgumentBlock& args); +__LIBC_HIDDEN__ void __libc_init_common(); -__LIBC_HIDDEN__ void __libc_init_AT_SECURE(KernelArgumentBlock& args); +__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp); #endif diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 08d3df4ff..25d462f8c 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -84,9 +84,8 @@ static void __libc_preinit_impl(KernelArgumentBlock& args) { __libc_init_sysinfo(args); #endif - __libc_shared_globals = args.shared_globals; __libc_init_globals(args); - __libc_init_common(args); + __libc_init_common(); // Hooks for various libraries to let them know that we're starting up. __libc_globals.mutate(__libc_init_malloc); @@ -138,7 +137,13 @@ __noreturn void __libc_init(void* raw_args, __cxa_atexit(__libc_fini,structors->fini_array,nullptr); } - exit(slingshot(args.argc - __libc_shared_globals->initial_linker_arg_count, - args.argv + __libc_shared_globals->initial_linker_arg_count, + exit(slingshot(args.argc - __libc_shared_globals()->initial_linker_arg_count, + args.argv + __libc_shared_globals()->initial_linker_arg_count, args.envp)); } + +extern "C" libc_shared_globals* __loader_shared_globals(); + +__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() { + return __loader_shared_globals(); +} diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index ef1c393dd..51fbe07bf 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -96,18 +96,15 @@ __noreturn static void __real_libc_init(void *raw_args, BIONIC_STOP_UNWIND; KernelArgumentBlock args(raw_args); + __libc_shared_globals()->init_progname = args.argv[0]; // Initializing the globals requires TLS to be available for errno. __libc_init_main_thread(args); - static libc_shared_globals shared_globals; - __libc_shared_globals = &shared_globals; - __libc_init_shared_globals(&shared_globals); - __libc_init_globals(args); - __libc_init_AT_SECURE(args); - __libc_init_common(args); + __libc_init_AT_SECURE(args.envp); + __libc_init_common(); apply_gnu_relro(); @@ -155,3 +152,10 @@ extern "C" int android_get_application_target_sdk_version() { extern "C" void android_set_application_target_sdk_version(int target) { g_target_sdk_version = target; } + +__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() { + static libc_shared_globals globals = { + .abort_msg_lock = PTHREAD_MUTEX_INITIALIZER, + }; + return &globals; +} diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h index 886dd32a0..c8ce8411f 100644 --- a/libc/private/KernelArgumentBlock.h +++ b/libc/private/KernelArgumentBlock.h @@ -23,9 +23,6 @@ #include "private/bionic_macros.h" -struct abort_msg_t; -struct libc_shared_globals; - // When the kernel starts the dynamic linker, it passes a pointer to a block // of memory containing argc, the argv array, the environment variable array, // and the array of ELF aux vectors. This class breaks that block up into its @@ -65,10 +62,6 @@ class KernelArgumentBlock { char** envp; ElfW(auxv_t)* auxv; - // Other data that we want to pass from the dynamic linker to libc.so. - abort_msg_t** abort_message_ptr; - libc_shared_globals* shared_globals; - private: BIONIC_DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock); }; diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h index 8c005512b..906d569d9 100644 --- a/libc/private/bionic_globals.h +++ b/libc/private/bionic_globals.h @@ -30,6 +30,7 @@ #define _PRIVATE_BIONIC_GLOBALS_H #include <sys/cdefs.h> +#include <pthread.h> #include "private/bionic_fdsan.h" #include "private/bionic_malloc_dispatch.h" @@ -44,6 +45,8 @@ struct libc_globals { __LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals; +struct abort_msg_t; + // Globals shared between the dynamic linker and libc.so. struct libc_shared_globals { FdTable fd_table; @@ -52,10 +55,16 @@ struct libc_shared_globals { // record the number of arguments passed to the linker itself rather than to // the program it's loading. Typically 0, sometimes 1. int initial_linker_arg_count; + + pthread_mutex_t abort_msg_lock; + abort_msg_t* abort_msg; + + // Values passed from the linker to libc.so. + const char* init_progname; + char** init_environ; }; -__LIBC_HIDDEN__ extern libc_shared_globals* __libc_shared_globals; -__LIBC_HIDDEN__ void __libc_init_shared_globals(libc_shared_globals*); +__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals(); __LIBC_HIDDEN__ void __libc_init_fdsan(); class KernelArgumentBlock; diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 45ae6ed7a..5ae7b9b19 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -38,6 +38,7 @@ #include <android/api-level.h> #include <bionic/pthread_internal.h> +#include "private/bionic_globals.h" #include "private/bionic_tls.h" #include "private/ScopedPthreadMutexLocker.h" @@ -86,6 +87,7 @@ void* __loader_dlvsym(void* handle, const void* caller_addr) __LINKER_PUBLIC__; void __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__; void __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__; +libc_shared_globals* __loader_shared_globals() __LINKER_PUBLIC__; #if defined(__arm__) _Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__; #endif @@ -299,6 +301,10 @@ void __loader_remove_thread_local_dtor(void* dso_handle) { decrement_dso_handle_reference_counter(dso_handle); } +libc_shared_globals* __loader_shared_globals() { + return __libc_shared_globals(); +} + static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8))); static soinfo* __libdl_info = nullptr; diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp index 0528cd889..152c2e266 100644 --- a/linker/ld_android.cpp +++ b/linker/ld_android.cpp @@ -53,6 +53,7 @@ __strong_alias(__loader_dlsym, __internal_linker_error); __strong_alias(__loader_dlvsym, __internal_linker_error); __strong_alias(__loader_add_thread_local_dtor, __internal_linker_error); __strong_alias(__loader_remove_thread_local_dtor, __internal_linker_error); +__strong_alias(__loader_shared_globals, __internal_linker_error); #if defined(__arm__) __strong_alias(__loader_dl_unwind_find_exidx, __internal_linker_error); #endif diff --git a/linker/linker.arm.map b/linker/linker.arm.map index a58e7c802..be438caec 100644 --- a/linker/linker.arm.map +++ b/linker/linker.arm.map @@ -22,6 +22,7 @@ __loader_dl_unwind_find_exidx; __loader_add_thread_local_dtor; __loader_remove_thread_local_dtor; + __loader_shared_globals; rtld_db_dlactivity; local: *; diff --git a/linker/linker.generic.map b/linker/linker.generic.map index 45bb0b500..f3c01c09f 100644 --- a/linker/linker.generic.map +++ b/linker/linker.generic.map @@ -21,6 +21,7 @@ __loader_android_get_exported_namespace; __loader_add_thread_local_dtor; __loader_remove_thread_local_dtor; + __loader_shared_globals; rtld_db_dlactivity; local: *; diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 82b10b74b..aa12b6ef1 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -116,7 +116,6 @@ soinfo* solist_get_vdso() { } int g_ld_debug_verbosity; -abort_msg_t* g_abort_message = nullptr; // For debuggerd. static std::vector<std::string> g_ld_preload_names; @@ -299,7 +298,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load #endif // Sanitize the environment. - __libc_init_AT_SECURE(args); + __libc_init_AT_SECURE(args.envp); // Initialize system properties __system_properties_init(); // may use 'environ' @@ -308,7 +307,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load #ifdef __ANDROID__ debuggerd_callbacks_t callbacks = { .get_abort_message = []() { - return g_abort_message; + return __libc_shared_globals()->abort_msg; }, .post_dump = ¬ify_gdb_of_libraries, }; @@ -630,12 +629,6 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) // couldn't make system calls on x86 at that point, but we can now... if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]); - // Initialize the linker/libc.so shared global inside the linker. - static libc_shared_globals shared_globals; - __libc_shared_globals = &shared_globals; - __libc_init_shared_globals(&shared_globals); - args.shared_globals = __libc_shared_globals; - // Initialize the linker's static libc's globals __libc_init_globals(args); @@ -663,13 +656,14 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) exit(0); } exe_to_load = args.argv[1]; - __libc_shared_globals->initial_linker_arg_count = 1; + __libc_shared_globals()->initial_linker_arg_count = 1; } // store argc/argv/envp to use them for calling constructors - g_argc = args.argc - __libc_shared_globals->initial_linker_arg_count; - g_argv = args.argv + __libc_shared_globals->initial_linker_arg_count; + g_argc = args.argc - __libc_shared_globals()->initial_linker_arg_count; + g_argv = args.argv + __libc_shared_globals()->initial_linker_arg_count; g_envp = args.envp; + __libc_shared_globals()->init_progname = g_argv[0]; // Initialize static variables. Note that in order to // get correct libdl_info we need to call constructors @@ -678,7 +672,6 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) g_default_namespace.add_soinfo(solinker); init_link_map_head(*solinker, kLinkerPath); - args.abort_message_ptr = &g_abort_message; ElfW(Addr) start_address = linker_main(args, exe_to_load); INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address)); diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp index 18ba011b0..57d04e94a 100644 --- a/tests/dl_test.cpp +++ b/tests/dl_test.cpp @@ -104,6 +104,7 @@ TEST(dl, exec_linker_load_file) { std::string expected_output = "ctor: argc=1 argv[0]=" + helper + "\n" + "main: argc=1 argv[0]=" + helper + "\n" + + "__progname=" + helper + "\n" + "helper_func called\n"; ExecTestHelper eth; eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr }); @@ -118,6 +119,7 @@ TEST(dl, exec_linker_load_from_zip) { std::string expected_output = "ctor: argc=1 argv[0]=" + helper + "\n" + "main: argc=1 argv[0]=" + helper + "\n" + + "__progname=" + helper + "\n" + "helper_func called\n"; ExecTestHelper eth; eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr }); diff --git a/tests/libs/exec_linker_helper.cpp b/tests/libs/exec_linker_helper.cpp index 01a61e091..56b1eafe0 100644 --- a/tests/libs/exec_linker_helper.cpp +++ b/tests/libs/exec_linker_helper.cpp @@ -28,7 +28,8 @@ #include <stdio.h> -extern "C" void _start(); +extern "C" const char* __progname; + const char* helper_func(); __attribute__((constructor)) @@ -38,6 +39,7 @@ static void ctor(int argc, char* argv[]) { int main(int argc, char* argv[]) { printf("main: argc=%d argv[0]=%s\n", argc, argv[0]); + printf("__progname=%s\n", __progname); printf("%s\n", helper_func()); return 0; } |