diff options
-rw-r--r-- | Userland/Libraries/LibC/crt0.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibC/cxxabi.cpp | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibC/sys/internals.h | 1 |
3 files changed, 15 insertions, 3 deletions
diff --git a/Userland/Libraries/LibC/crt0.cpp b/Userland/Libraries/LibC/crt0.cpp index ae2b96d443..798f7c751b 100644 --- a/Userland/Libraries/LibC/crt0.cpp +++ b/Userland/Libraries/LibC/crt0.cpp @@ -39,6 +39,7 @@ int _entry(int argc, char** argv, char** env) environ = env; __environ_is_malloced = false; + __begin_atexit_locking(); _init(); diff --git a/Userland/Libraries/LibC/cxxabi.cpp b/Userland/Libraries/LibC/cxxabi.cpp index 44c0855ab6..42f830afa3 100644 --- a/Userland/Libraries/LibC/cxxabi.cpp +++ b/Userland/Libraries/LibC/cxxabi.cpp @@ -32,9 +32,13 @@ static AtExitEntry* atexit_entries; static size_t atexit_entry_count = 0; static pthread_mutex_t atexit_mutex = __PTHREAD_MUTEX_INITIALIZER; +// During startup, it is sufficiently unlikely that the attacker can exploit any write primitive. +// We use this to avoid unnecessary syscalls to mprotect. +static bool atexit_region_should_lock = false; + static void lock_atexit_handlers() { - if (mprotect(atexit_entries, atexit_entry_region_size, PROT_READ) < 0) { + if (atexit_region_should_lock && mprotect(atexit_entries, atexit_entry_region_size, PROT_READ) < 0) { perror("lock_atexit_handlers"); _exit(1); } @@ -42,19 +46,25 @@ static void lock_atexit_handlers() static void unlock_atexit_handlers() { - if (mprotect(atexit_entries, atexit_entry_region_size, PROT_READ | PROT_WRITE) < 0) { + if (atexit_region_should_lock && mprotect(atexit_entries, atexit_entry_region_size, PROT_READ | PROT_WRITE) < 0) { perror("unlock_atexit_handlers"); _exit(1); } } +void __begin_atexit_locking() +{ + atexit_region_should_lock = true; + lock_atexit_handlers(); +} + int __cxa_atexit(AtExitFunction exit_function, void* parameter, void* dso_handle) { __pthread_mutex_lock(&atexit_mutex); // allocate initial atexit region if (!atexit_entries) { - atexit_entries = (AtExitEntry*)mmap(nullptr, atexit_entry_region_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + atexit_entries = (AtExitEntry*)mmap(nullptr, atexit_entry_region_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); if (atexit_entries == MAP_FAILED) { __pthread_mutex_unlock(&atexit_mutex); perror("__cxa_atexit mmap"); diff --git a/Userland/Libraries/LibC/sys/internals.h b/Userland/Libraries/LibC/sys/internals.h index b18115a377..4a275b2801 100644 --- a/Userland/Libraries/LibC/sys/internals.h +++ b/Userland/Libraries/LibC/sys/internals.h @@ -15,6 +15,7 @@ typedef void (*AtExitFunction)(void*); extern void __libc_init(); extern void __malloc_init(); extern void __stdio_init(); +extern void __begin_atexit_locking(); extern void _init(); extern bool __environ_is_malloced; extern bool __stdio_is_initialized; |