From c9a6bcf81dd1bc493ba29b7e87f10bc5c5646a7b Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Sat, 20 Apr 2024 19:33:27 -0400 Subject: [PATCH] LibC+LibELF: Use AT_RANDOM ELF auxiliary vector for __stack_chk_guard Kernel provided it for about 4 years at this point. I think it is about time to finally use it in userspace. --- Userland/DynamicLoader/main.cpp | 17 ++++++++--- Userland/Libraries/LibC/libcinit.cpp | 32 ++++++++++++--------- Userland/Libraries/LibC/sys/internals.h | 2 +- Userland/Libraries/LibELF/DynamicLinker.cpp | 7 +---- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp index 627658fa466..2822c0d7b83 100644 --- a/Userland/DynamicLoader/main.cpp +++ b/Userland/DynamicLoader/main.cpp @@ -16,9 +16,7 @@ char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds.. char** environ = __static_environ; - -// FIXME: Kernel should give us a random value for __stack_chk_guard. -uintptr_t __stack_chk_guard = 0xe0e6'066b'b7ea'c300; +uintptr_t __stack_chk_guard = 0; static void perform_self_relocations(auxv_t* auxvp) { @@ -112,11 +110,22 @@ void _entry(int argc, char** argv, char** envp) } auxv_t* auxvp = (auxv_t*)++env; + + bool at_random_found = false; + for (auxv_t* entry = auxvp; entry->a_type != AT_NULL; ++entry) { + if (entry->a_type == AT_RANDOM) { + at_random_found = true; + __stack_chk_guard = *reinterpret_cast(entry->a_un.a_ptr); + break; + } + } + VERIFY(at_random_found); + perform_self_relocations(auxvp); // Initialize the copy of libc included statically in Loader.so, // initialization of the dynamic libc.so is done by the DynamicLinker - __libc_init(0); + __libc_init(); int main_program_fd = -1; ByteString main_program_path; diff --git a/Userland/Libraries/LibC/libcinit.cpp b/Userland/Libraries/LibC/libcinit.cpp index dafa444683e..11148fd9394 100644 --- a/Userland/Libraries/LibC/libcinit.cpp +++ b/Userland/Libraries/LibC/libcinit.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -28,30 +29,33 @@ char** environ = reinterpret_cast(explode_byte(0xe2)); uintptr_t __stack_chk_guard; #endif -static void __auxiliary_vector_init(); - int* __errno_location() { return &errno_storage; } -void __libc_init([[maybe_unused]] uintptr_t cookie) +void __libc_init() { #ifndef _DYNAMIC_LOADER - __stack_chk_guard = cookie; + // We can only call magic functions until __stack_chk_guard is initialized. environ = __environ_value(); #endif - __auxiliary_vector_init(); + + char** env; + for (env = environ; *env; ++env) + ; + __auxiliary_vector = (void*)++env; + +#ifndef _DYNAMIC_LOADER + for (auxv_t* entry = reinterpret_cast(__auxiliary_vector); entry->a_type != AT_NULL; ++entry) + if (entry->a_type == AT_RANDOM) + __stack_chk_guard = *(reinterpret_cast(entry->a_un.a_ptr) + 1); + + // We include an additional hardening: zero the first byte of the stack guard to avoid leaking + // or overwriting the stack guard with C-style string functions. + __stack_chk_guard &= ~0xffULL; +#endif __malloc_init(); __stdio_init(); } - -static void __auxiliary_vector_init() -{ - char** env; - for (env = environ; *env; ++env) { - } - - __auxiliary_vector = (void*)++env; -} } diff --git a/Userland/Libraries/LibC/sys/internals.h b/Userland/Libraries/LibC/sys/internals.h index 415675e7451..e88b66fc543 100644 --- a/Userland/Libraries/LibC/sys/internals.h +++ b/Userland/Libraries/LibC/sys/internals.h @@ -13,7 +13,7 @@ __BEGIN_DECLS typedef void (*AtExitFunction)(void*); -extern void __libc_init(uintptr_t); +extern void __libc_init(); extern void __malloc_init(void); extern void __stdio_init(void); extern void __begin_atexit_locking(void); diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index 404a7dbf7ec..7e9e963d0dd 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/Userland/Libraries/LibELF/DynamicLinker.cpp @@ -315,15 +315,10 @@ static int __dl_iterate_phdr(DlIteratePhdrCallbackFunction callback, void* data) static void initialize_libc(DynamicObject& libc) { - uintptr_t stack_guard = get_random(); - // We include an additional hardening: zero the first byte of the stack guard to avoid leaking - // or overwriting the stack guard with C-style string functions. - stack_guard &= ~0xffULL; - auto res = libc.lookup_symbol("__libc_init"sv); VERIFY(res.has_value()); using libc_init_func = decltype(__libc_init); - ((libc_init_func*)res.value().address.as_ptr())(stack_guard); + ((libc_init_func*)res.value().address.as_ptr())(); } template