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.
This commit is contained in:
Dan Klishch 2024-04-20 19:33:27 -04:00 committed by Andrew Kaster
commit c9a6bcf81d
Notes: sideshowbarker 2024-07-16 20:51:53 +09:00
4 changed files with 33 additions and 25 deletions

View file

@ -16,9 +16,7 @@
char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds.. char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds..
char** environ = __static_environ; char** environ = __static_environ;
uintptr_t __stack_chk_guard = 0;
// FIXME: Kernel should give us a random value for __stack_chk_guard.
uintptr_t __stack_chk_guard = 0xe0e6'066b'b7ea'c300;
static void perform_self_relocations(auxv_t* auxvp) 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; 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<u64*>(entry->a_un.a_ptr);
break;
}
}
VERIFY(at_random_found);
perform_self_relocations(auxvp); perform_self_relocations(auxvp);
// Initialize the copy of libc included statically in Loader.so, // Initialize the copy of libc included statically in Loader.so,
// initialization of the dynamic libc.so is done by the DynamicLinker // initialization of the dynamic libc.so is done by the DynamicLinker
__libc_init(0); __libc_init();
int main_program_fd = -1; int main_program_fd = -1;
ByteString main_program_path; ByteString main_program_path;

View file

@ -7,6 +7,7 @@
#include <AK/Types.h> #include <AK/Types.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <sys/auxv.h>
#include <sys/internals.h> #include <sys/internals.h>
#include <unistd.h> #include <unistd.h>
@ -28,30 +29,33 @@ char** environ = reinterpret_cast<char**>(explode_byte(0xe2));
uintptr_t __stack_chk_guard; uintptr_t __stack_chk_guard;
#endif #endif
static void __auxiliary_vector_init();
int* __errno_location() int* __errno_location()
{ {
return &errno_storage; return &errno_storage;
} }
void __libc_init([[maybe_unused]] uintptr_t cookie) void __libc_init()
{ {
#ifndef _DYNAMIC_LOADER #ifndef _DYNAMIC_LOADER
__stack_chk_guard = cookie; // We can only call magic functions until __stack_chk_guard is initialized.
environ = __environ_value(); environ = __environ_value();
#endif #endif
__auxiliary_vector_init();
char** env;
for (env = environ; *env; ++env)
;
__auxiliary_vector = (void*)++env;
#ifndef _DYNAMIC_LOADER
for (auxv_t* entry = reinterpret_cast<auxv_t*>(__auxiliary_vector); entry->a_type != AT_NULL; ++entry)
if (entry->a_type == AT_RANDOM)
__stack_chk_guard = *(reinterpret_cast<u64*>(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(); __malloc_init();
__stdio_init(); __stdio_init();
} }
static void __auxiliary_vector_init()
{
char** env;
for (env = environ; *env; ++env) {
}
__auxiliary_vector = (void*)++env;
}
} }

View file

@ -13,7 +13,7 @@ __BEGIN_DECLS
typedef void (*AtExitFunction)(void*); typedef void (*AtExitFunction)(void*);
extern void __libc_init(uintptr_t); extern void __libc_init();
extern void __malloc_init(void); extern void __malloc_init(void);
extern void __stdio_init(void); extern void __stdio_init(void);
extern void __begin_atexit_locking(void); extern void __begin_atexit_locking(void);

View file

@ -315,15 +315,10 @@ static int __dl_iterate_phdr(DlIteratePhdrCallbackFunction callback, void* data)
static void initialize_libc(DynamicObject& libc) static void initialize_libc(DynamicObject& libc)
{ {
uintptr_t stack_guard = get_random<uintptr_t>();
// 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); auto res = libc.lookup_symbol("__libc_init"sv);
VERIFY(res.has_value()); VERIFY(res.has_value());
using libc_init_func = decltype(__libc_init); 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<typename Callback> template<typename Callback>