summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibC/crt0.cpp1
-rw-r--r--Userland/Libraries/LibC/cxxabi.cpp16
-rw-r--r--Userland/Libraries/LibC/sys/internals.h1
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;