From 9317256a4f3c76d4ce70741a357e5aadcda58529 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 24 Feb 2021 15:14:17 -0800 Subject: [PATCH] improved ASLR (issue #372) --- src/os.c | 11 +++++++++-- test/main-override.cpp | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/os.c b/src/os.c index 4071f65c..ebe5a6d1 100644 --- a/src/os.c +++ b/src/os.c @@ -465,10 +465,17 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro #if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED))) static mi_decl_cache_align _Atomic(uintptr_t) aligned_base; -// Return a 4MiB aligned address that is probably available -static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) { +// Return a 4MiB aligned address that is probably available. +// If this returns NULL, the OS will determine the address but on some OS's that may not be +// properly aligned which can be more costly as it needs to be adjusted afterwards. +// For a size > 4GiB this always returns NULL in order to guarantee good ASLR randomization; +// otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses +// in the middle of the 4TiB - 8TiB address range (see issue #372). +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) +{ if (try_alignment == 0 || try_alignment > MI_SEGMENT_SIZE) return NULL; if ((size%MI_SEGMENT_SIZE) != 0) return NULL; + if (size > 1*GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(4<<40 / 1<<30) = 1/4096. uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size); if (hint == 0 || hint > ((intptr_t)30<<40)) { // try to wrap around after 30TiB (area after 32TiB is used for huge OS pages) uintptr_t init = ((uintptr_t)4 << 40); // start at 4TiB area diff --git a/test/main-override.cpp b/test/main-override.cpp index fe5403d1..e8d2bfa5 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -32,6 +32,7 @@ void heap_late_free(); // issue #204 void padding_shrink(); // issue #209 void various_tests(); void test_mt_shutdown(); +void fail_aslr(); // issue #372 int main() { mi_stats_reset(); // ignore earlier allocations @@ -41,6 +42,7 @@ int main() { padding_shrink(); various_tests(); //test_mt_shutdown(); + //test_aslr(); mi_stats_print(NULL); return 0; } @@ -207,3 +209,11 @@ void test_mt_shutdown() std::cout << "done" << std::endl; } + +// issue #372 +void fail_aslr() { + size_t sz = (4ULL << 40); // 4TiB + void* p = malloc(sz); + printf("pointer p: %p: area up to %p\n", p, (uint8_t*)p + sz); + *(int*)0x7FFFFFFF000 = 0; // should segfault +} \ No newline at end of file