diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Android.bp | 87 | ||||
-rw-r--r-- | libc/bionic/__libc_init_main_thread.cpp | 24 | ||||
-rw-r--r-- | libc/bionic/bionic_call_ifunc_resolver.cpp | 22 | ||||
-rw-r--r-- | libc/bionic/getauxval.cpp | 1 | ||||
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 3 | ||||
-rw-r--r-- | libc/bionic/pthread_create.cpp | 19 |
6 files changed, 96 insertions, 60 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index 53a26a64a..c5ea4c522 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -142,19 +142,21 @@ cc_defaults { } // ======================================================== -// libc_stack_protector.a - stack protector code +// libc_bootstrap.a - -fno-stack-protector and -ffreestanding // ======================================================== // -// Code that implements the stack protector (or that runs -// before TLS has been set up) needs to be compiled with -// -fno-stack-protector, since it accesses the stack canary -// TLS slot. +// Code that implements the stack protector (or that runs before TLS has been set up) needs to be +// compiled with -fno-stack-protector, since it accesses the stack canary TLS slot. In the linker, +// some of this code runs before ifunc resolvers have made string.h functions work, so compile with +// -ffreestanding. cc_library_static { srcs: [ "bionic/__libc_init_main_thread.cpp", "bionic/__stack_chk_fail.cpp", + "bionic/bionic_call_ifunc_resolver.cpp", + "bionic/getauxval.cpp", ], arch: { arm64: { @@ -172,20 +174,25 @@ cc_library_static { }, defaults: ["libc_defaults"], - cflags: ["-fno-stack-protector"], - name: "libc_stack_protector", + cflags: ["-fno-stack-protector", "-ffreestanding"], + name: "libc_bootstrap", } -// libc_init_static.cpp also needs to be built without stack protector, -// because it's responsible for setting up TLS for static executables. -// This isn't the case for dynamic executables because the dynamic linker -// has already set up the main thread's TLS. +// libc_init_static.cpp and libc_init_dynamic.cpp need to be built without stack protector. +// libc_init_static.cpp sets up TLS for static executables, and libc_init_dynamic.cpp initializes +// the stack protector global variable. cc_library_static { name: "libc_init_static", defaults: ["libc_defaults"], srcs: ["bionic/libc_init_static.cpp"], - cflags: ["-fno-stack-protector"], + cflags: [ + "-fno-stack-protector", + + // Compile libc_init_static.cpp with -ffreestanding, because some of its code is called + // from the linker before ifunc resolvers have made string.h functions available. + "-ffreestanding", + ], } cc_library_static { @@ -784,12 +791,6 @@ cc_library_static { cc_library_static { defaults: ["libc_defaults"], srcs: [ - // The data that backs getauxval is initialized in the libc init - // functions which are invoked by the linker. If this file is included - // in libc_ndk.a, only one of the copies of the global data will be - // initialized, resulting in nullptr dereferences. - "bionic/getauxval.cpp", - // These require getauxval, which isn't available on older platforms. "bionic/sysconf.cpp", "bionic/vdso.cpp", @@ -1084,7 +1085,6 @@ cc_library_static { "bionic/atof.cpp", "bionic/bionic_allocator.cpp", "bionic/bionic_arc4random.cpp", - "bionic/bionic_call_ifunc_resolver.cpp", "bionic/bionic_futex.cpp", "bionic/bionic_netlink.cpp", "bionic/bionic_systrace.cpp", @@ -1427,6 +1427,7 @@ cc_library_static { whole_static_libs: [ "libc_bionic_ndk", + "libc_bootstrap", "libc_fortify", "libc_freebsd", "libc_freebsd_large_stack", @@ -1434,7 +1435,6 @@ cc_library_static { "libc_netbsd", "libc_openbsd_large_stack", "libc_openbsd_ndk", - "libc_stack_protector", "libc_syscalls", "libc_tzcode", "libm", @@ -1458,6 +1458,7 @@ cc_library_static { whole_static_libs: [ "libc_bionic", "libc_bionic_ndk", + "libc_bootstrap", "libc_dns", "libc_fortify", "libc_freebsd", @@ -1467,7 +1468,6 @@ cc_library_static { "libc_openbsd", "libc_openbsd_large_stack", "libc_openbsd_ndk", - "libc_stack_protector", "libc_syscalls", "libc_tzcode", "libstdc++", @@ -1495,11 +1495,11 @@ cc_library_static { } // ======================================================== -// libc_common_static.a For static binaries. +// libc_static_dispatch.a // ======================================================== cc_library_static { defaults: ["libc_defaults"], - name: "libc_common_static", + name: "libc_static_dispatch", arch: { x86: { @@ -1512,18 +1512,14 @@ cc_library_static { srcs: ["arch-arm64/static_function_dispatch.S"], }, }, - - whole_static_libs: [ - "libc_common", - ], } // ======================================================== -// libc_common_shared.a For shared libraries. +// libc_dynamic_dispatch.a // ======================================================== cc_library_static { defaults: ["libc_defaults"], - name: "libc_common_shared", + name: "libc_dynamic_dispatch", cflags: [ "-ffreestanding", @@ -1541,9 +1537,31 @@ cc_library_static { srcs: ["arch-arm64/dynamic_function_dispatch.cpp"], }, }, +} + +// ======================================================== +// libc_common_static.a For static binaries. +// ======================================================== +cc_library_static { + defaults: ["libc_defaults"], + name: "libc_common_static", whole_static_libs: [ "libc_common", + "libc_static_dispatch", + ], +} + +// ======================================================== +// libc_common_shared.a For shared libraries. +// ======================================================== +cc_library_static { + defaults: ["libc_defaults"], + name: "libc_common_shared", + + whole_static_libs: [ + "libc_common", + "libc_dynamic_dispatch", ], } @@ -1567,19 +1585,16 @@ cc_library_static { // libc_nomalloc.a // ======================================================== // -// This is a version of the static C library that does not -// include malloc. It's useful in situations when the user wants -// to provide their own malloc implementation, or wants to -// explicitly disallow the use of malloc, such as in the -// dynamic linker. +// This is a version of the static C library used by the dynamic linker that exclude malloc. It also +// excludes functions selected using ifunc's (e.g. for string.h). Link in either +// libc_static_dispatch or libc_dynamic_dispatch to provide those functions. cc_library_static { name: "libc_nomalloc", defaults: ["libc_defaults"], - cflags: ["-DLIBC_STATIC"], whole_static_libs: [ - "libc_common_static", + "libc_common", "libc_init_static", "libc_unwind_static", ], diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp index 6e1b0de25..94cf1f8e3 100644 --- a/libc/bionic/__libc_init_main_thread.cpp +++ b/libc/bionic/__libc_init_main_thread.cpp @@ -57,7 +57,9 @@ static pthread_internal_t main_thread; // // This is in a file by itself because it needs to be built with // -fno-stack-protector because it's responsible for setting up the main -// thread's TLS (which stack protector relies on). +// thread's TLS (which stack protector relies on). It's also built with +// -ffreestanding because the early init function runs in the linker before +// ifunc resolvers have run. // Do enough setup to: // - Let the dynamic linker invoke system calls (and access errno) @@ -65,7 +67,8 @@ static pthread_internal_t main_thread; // - Allow the stack protector to work (with a zero cookie) // Avoid doing much more because, when this code is called within the dynamic // linker, the linker binary hasn't been relocated yet, so certain kinds of code -// are hazardous, such as accessing non-hidden global variables. +// are hazardous, such as accessing non-hidden global variables or calling +// string.h functions. __BIONIC_WEAK_FOR_NATIVE_BRIDGE extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, bionic_tcb* temp_tcb) { @@ -80,6 +83,23 @@ extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, main_thread.set_cached_pid(main_thread.tid); } +// This code is used both by each new pthread and the code that initializes the main thread. +void __init_tcb(bionic_tcb* tcb, pthread_internal_t* thread) { +#ifdef TLS_SLOT_SELF + // On x86, slot 0 must point to itself so code can read the thread pointer by + // loading %fs:0 or %gs:0. + tcb->tls_slot(TLS_SLOT_SELF) = &tcb->tls_slot(TLS_SLOT_SELF); +#endif + tcb->tls_slot(TLS_SLOT_THREAD_ID) = thread; +} + +void __init_tcb_dtv(bionic_tcb* tcb) { + // Initialize the DTV slot to a statically-allocated empty DTV. The first + // access to a dynamic TLS variable allocates a new DTV. + static const TlsDtv zero_dtv = {}; + __set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv)); +} + // Finish initializing the main thread. __BIONIC_WEAK_FOR_NATIVE_BRIDGE extern "C" void __libc_init_main_thread_late() { diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp index 85228359e..437de78ce 100644 --- a/libc/bionic/bionic_call_ifunc_resolver.cpp +++ b/libc/bionic/bionic_call_ifunc_resolver.cpp @@ -30,14 +30,32 @@ #include <sys/auxv.h> #include <sys/ifunc.h> +#include "private/bionic_auxv.h" + +// This code is called in the linker before it has been relocated, so minimize calls into other +// parts of Bionic. In particular, we won't ever have two ifunc resolvers called concurrently, so +// initializing the ifunc resolver argument doesn't need to be thread-safe. + ElfW(Addr) __bionic_call_ifunc_resolver(ElfW(Addr) resolver_addr) { #if defined(__aarch64__) typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __ifunc_arg_t*); - static __ifunc_arg_t arg = { sizeof(__ifunc_arg_t), getauxval(AT_HWCAP), getauxval(AT_HWCAP2) }; + static __ifunc_arg_t arg; + static bool initialized = false; + if (!initialized) { + initialized = true; + arg._size = sizeof(__ifunc_arg_t); + arg._hwcap = getauxval(AT_HWCAP); + arg._hwcap2 = getauxval(AT_HWCAP2); + } return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg); #elif defined(__arm__) typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long); - static unsigned long hwcap = getauxval(AT_HWCAP); + static unsigned long hwcap; + static bool initialized = false; + if (!initialized) { + initialized = true; + hwcap = getauxval(AT_HWCAP); + } return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap); #else typedef ElfW(Addr) (*ifunc_resolver_t)(void); diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp index c8f867b64..f865f97b4 100644 --- a/libc/bionic/getauxval.cpp +++ b/libc/bionic/getauxval.cpp @@ -36,7 +36,6 @@ // This function needs to be safe to call before TLS is set up, so it can't // access errno or the stack protector. -__attribute__((no_stack_protector)) __LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists) { for (ElfW(auxv_t)* v = __libc_shared_globals()->auxv; v->a_type != AT_NULL; ++v) { if (v->a_type == type) { diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index 0b740232a..28c0b0c95 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -231,6 +231,9 @@ extern "C" void android_set_application_target_sdk_version(int target) { g_target_sdk_version = target; } +// This function is called in the dynamic linker before ifunc resolvers have run, so this file is +// compiled with -ffreestanding to avoid implicit string.h function calls. (It shouldn't strictly +// be necessary, though.) __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() { static libc_shared_globals globals; return &globals; diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index 1dc10667b..03af2d94a 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -54,31 +54,12 @@ void __init_user_desc(struct user_desc*, bool, void*); #endif -// This code is used both by each new pthread and the code that initializes the main thread. -__attribute__((no_stack_protector)) -void __init_tcb(bionic_tcb* tcb, pthread_internal_t* thread) { -#ifdef TLS_SLOT_SELF - // On x86, slot 0 must point to itself so code can read the thread pointer by - // loading %fs:0 or %gs:0. - tcb->tls_slot(TLS_SLOT_SELF) = &tcb->tls_slot(TLS_SLOT_SELF); -#endif - tcb->tls_slot(TLS_SLOT_THREAD_ID) = thread; -} - __attribute__((no_stack_protector)) void __init_tcb_stack_guard(bionic_tcb* tcb) { // GCC looks in the TLS for the stack guard on x86, so copy it there from our global. tcb->tls_slot(TLS_SLOT_STACK_GUARD) = reinterpret_cast<void*>(__stack_chk_guard); } -__attribute__((no_stack_protector)) -void __init_tcb_dtv(bionic_tcb* tcb) { - // Initialize the DTV slot to a statically-allocated empty DTV. The first - // access to a dynamic TLS variable allocates a new DTV. - static const TlsDtv zero_dtv = {}; - __set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv)); -} - void __init_bionic_tls_ptrs(bionic_tcb* tcb, bionic_tls* tls) { tcb->thread()->bionic_tls = tls; tcb->tls_slot(TLS_SLOT_BIONIC_TLS) = tls; |