Authors: | Hector Marco & Ismael Ripoll |
CVE: | CVE-2016-3672 |
Dates: | April 2016 |
Any user, able to run 32-bit applications in a x86 machine, can disable the ASLR by setting the RLIMIT_STACK resource to unlimited.
Following are the steps to test whether your system is vulnerable or not:
1) Create a dummy program which shows its memory map:#include <stdio.h> int main(int argc, const char *argv[]) { char cmd[256]; sprintf(cmd, "cat /proc/%d/maps", getpid()); system(cmd); return 0; }2) Compile it:
$ gcc show_maps.c -o show_maps # In a i386 machine $ gcc show_maps.c -o show_maps -m32 # In a 64-bit machine3) Run the application to check that ASLR is working
$ for i in `seq 1 10`; do ./show_maps | grep "r-xp.*libc"; done f75c4000-f7769000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f75db000-f7780000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f7557000-f76fc000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f7595000-f773a000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f7574000-f7719000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f75af000-f7754000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f7530000-f76d5000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f7529000-f76ce000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f75c2000-f7767000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so f75fe000-f77a3000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.soThe libc-2.19.so library is mapped at random positions, so, the ASLR is working properly.
Now, we run the same test but setting the stack to unlimited:
$ ulimit -a | grep stack stack size (kbytes, -s) 8192 $ ulimit -s unlimited stack size (kbytes, -s) unlimited $ for i in `seq 1 10`; do ./show_maps | grep "r-xp.*libc"; done 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.so 5559a000-5573f000 r-xp 00000000 08:01 784726 /lib32/libc-2.19.soThe libc-2.19.so library is mapped at the same position in all executions: the ASLR has been disabled.
This is a very old trick to disable ASLR, but unfortunately it was still present in current Linux systems.
static unsigned long mmap_legacy_base(void)
{
if (mmap_is_ia32())
return TASK_UNMAPPED_BASE;
else
return TASK_UNMAPPED_BASE + mmap_rnd();
}
The function doesn't add any random offset when the system is running in a native 32-bit system (i386)
or a 32-bit emulated system (x86_32).
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 96bd1e2..389939f 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -94,18 +94,6 @@ static unsigned long mmap_base(unsigned long rnd) } /* - * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 - * does, but not when emulating X86_32 - */ -static unsigned long mmap_legacy_base(unsigned long rnd) -{ - if (mmap_is_ia32()) - return TASK_UNMAPPED_BASE; - else - return TASK_UNMAPPED_BASE + rnd; -} - -/* * This function, called very early during the creation of a new * process VM image, sets up which VM layout function to use: */ @@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (current->flags & PF_RANDOMIZE) random_factor = arch_mmap_rnd(); - mm->mmap_legacy_base = mmap_legacy_base(random_factor); + mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor; if (mmap_is_legacy()) { mm->mmap_base = mm->mmap_legacy_base;The patch enables randomization for the libraries, vDSO and mmap requests on i386 and in X86_32 in legacy mode. We already sent the patch to Linux mantainers and the issue will be not problem in incomming Linux versions: Enable full randomization on i386 and X86_32