From e57533956428b4890421a5d5a7e4312e27859665 Mon Sep 17 00:00:00 2001 From: Keegan Saunders Date: Sun, 27 Nov 2022 15:46:17 -0500 Subject: [PATCH] LibELF: Add stack guard hardening Employ the same hardening that glibc and the Linux kernel use for generating stack guards: zero the first byte of the guard such that if C-style string functions read out of bounds on the stack, we do not overwrite or potentially leak the stack guard. --- Userland/Libraries/LibC/ssp.cpp | 1 + Userland/Libraries/LibELF/DynamicLinker.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibC/ssp.cpp b/Userland/Libraries/LibC/ssp.cpp index 8735f437d7..126a946b86 100644 --- a/Userland/Libraries/LibC/ssp.cpp +++ b/Userland/Libraries/LibC/ssp.cpp @@ -18,6 +18,7 @@ extern "C" { extern uintptr_t __stack_chk_guard; +// Initialized in `initialize_libc` (we leave a placeholder value here before initialization). __attribute__((used)) uintptr_t __stack_chk_guard = (uintptr_t)0xc6c7c8c9; __attribute__((noreturn)) void __stack_chk_fail() diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index ee4ee79eac..379bd57fec 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/Userland/Libraries/LibELF/DynamicLinker.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -258,7 +259,14 @@ static void initialize_libc(DynamicObject& libc) // This is not done in __libc_init, as we definitely have to return from that, and it might affect Loader as well. res = libc.lookup_symbol("__stack_chk_guard"sv); VERIFY(res.has_value()); - arc4random_buf(res.value().address.as_ptr(), sizeof(uintptr_t)); + void* stack_guard = res.value().address.as_ptr(); + arc4random_buf(stack_guard, sizeof(uintptr_t)); + +#ifdef AK_ARCH_64_BIT + // For 64-bit platforms 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. + ((char*)stack_guard)[0] = 0; +#endif res = libc.lookup_symbol("__environ_is_malloced"sv); VERIFY(res.has_value());