Date: Tue, 12 Mar 2019 20:30:06 -0500 From: Ali Saidi <asaidi@...il.com> To: oss-security@...ts.openwall.com Cc: alisaidi@...zon.com, "Liguori, Anthony" <aliguori@...zon.com>, dwmw@...zon.co.uk, pzb@...zon.com Subject: Stack/Heap Clashing on Linux >=4.13 when loader directly invoked Resending due to the original being dropped... Out of an abundance of caution this kernel issue was pre-disclosed with a suggested patch to linux-distros@ and a patch has now been sent to lkml ( https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=90691). In Linux 4.13 a change was committed that special cased the kernel ELF loader when the loader is invoked directly (eab09532d40090698b05a07c1c87f39fdbc5fab5; binfmt_elf: use ELF_ET_DYN_BASE only for PIE). Generally, the loader isn’t invoked directly and this issue is limited to cases where it is, (e.g to set a non-inheritable LD_LIBRARY_PATH, testing new versions of the loader). While this issue is found on an arm64 system, the issue exists for other architectures as well, with less frequency, and was observed occurring for both arm64 and x86_64. When ELF binary is loaded directly, the kernel loader places it at ELF_ET_DYN_BASE so there is a large separation between the stack and the heap. However, when the loader is run directly, the kernel portion of the loader sets load_bias = 0 which implies that mmap picks the address to load it at. It does this by picking an address no higher than mm->mmap_base. This address is calculated by starting at STACK_TOP and subtracting the stack size, the stack randomization, and mmap_rnd_bits on arm64. ----> STACK_TOP ----> STACK_RND (-1GB) ----> stack_guard_gap (-256KB) ----> mmap_base (-[0-1GB]) If heap randomization is enabled (randomize_va_space = 2) the kernel loader will call arch_randomize_brk() to also randomize the offset of the brk from the heap. On arm64 this adds up to 1GB of randomization as the default setting for mmap_rnd_bits is 1GB. Depending on the random offsets generated for the heap and stack we can end up with a situation where the stack randomization places the stack relatively far down in its region, the mmap randomization is relatively small, and the brk randomization is large leading to the stack and heap being arbitrarily close. ----> STACK_TOP (0x1000000000000) ----> bottom of stack (0xffffc067c4f0) ----> top of heap (0xffffc067c000) ----> STACK_RND (0xffffc0000000) ----> mmap_base (-0GB]) arm64 and x86 appear to do roughly the same thing here. Invoking a program via ld-linux.so directly on arm64 surfaces the issue after a few thousand invocations. On x86 arch_randomize_brk() is smaller (32MB) and the default setting for mmap_rnd_bits defaults to a 1TB which makes the situation much less likely to occur, but it’s still possible. The same should hold for other architectures but I haven’t confirmed it. Ali
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.