From bbfdaaae4406fa6df5e0decc7a96cb937da6c51f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Jan 2010 12:36:45 -0800 Subject: [PATCH] UBUNTU: SAUCE: x86: brk away from exec rand area This is a fix for the NX emulation patch to force the brk area well outside of the exec randomization area to avoid future allocation or brk growth collisions. Normally this isn't a problem, except when the text region has been loaded from a PIE binary and the CS limit can't be put just above bss. Additionally, the nx-emulation patch was still randomizing addresses even when randomize_va_space was disabled, which would cause collisions even faster if someone tried to disable randomization. BugLink: http://bugs.launchpad.net/bugs/452175 Signed-off-by: Kees Cook --- fs/binfmt_elf.c | 10 ++++++++++ mm/mmap.c | 11 ++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index b10acea..73594b9 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -978,6 +978,16 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) #ifdef arch_randomize_brk if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) current->mm->brk = current->mm->start_brk = +# ifdef CONFIG_X86_32 + /* in the case of NX emulation, shove the brk + segment way out of the way of the exec + randomization area, since it can collide with + future allocations if not. */ + ( (current->mm->get_unmapped_exec_area == + arch_get_unmapped_exec_area) && + (current->mm->brk < 0x08000000) + ? (TASK_SIZE/6) : 0) + +# endif arch_randomize_brk(current->mm); #endif diff --git a/mm/mmap.c b/mm/mmap.c index 814b95f..17ed65d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1516,8 +1516,11 @@ arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, if (flags & MAP_FIXED) return addr; - if (!addr) - addr = randomize_range(SHLIB_BASE, 0x01000000, len); + if (!addr) { + addr = SHLIB_BASE; + if ((current->flags & PF_RANDOMIZE) && randomize_va_space) + addr = randomize_range(addr, 0x01000000, len); + } if (addr) { addr = PAGE_ALIGN(addr); @@ -1545,7 +1548,9 @@ arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, * Up until the brk area we randomize addresses * as much as possible: */ - if (addr >= 0x01000000) { + if ((current->flags & PF_RANDOMIZE) && + randomize_va_space && + addr >= 0x01000000) { tmp = randomize_range(0x01000000, PAGE_ALIGN(max(mm->start_brk, (unsigned long)0x08000000)), len); -- 1.6.5