diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-07-14 00:55:23 -0700 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2011-09-23 08:50:55 -0600 |
commit | e0dd5cbe67c056d3bd3cf91b4c72f32519c83e49 (patch) | |
tree | e3e0a7470591f95cc5e438c17b77f5939b60948f /arch | |
parent | 9d11aa4b7e3e261c42c22275605339e01a2edee4 (diff) |
UBUNTU: ubuntu: nx-emu - i386: mmap randomization for executable mappings
This code is originally from Ingo Molnar, with some later rebasing and
fixes to respect all the randomization-disabling knobs. It provides
address randomization algorithm when NX emulation is in use in 32-bit
processes. Kees Cook pushed the brk area further away in the case of PIE
binaries landing their brk inside the CS limit.
Signed-off-by: Kees Cook <kees.cook@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/process.c | 12 | ||||
-rw-r--r-- | arch/x86/mm/mmap.c | 6 | ||||
-rw-r--r-- | arch/x86/vdso/vdso32-setup.c | 2 |
3 files changed, 18 insertions, 2 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e1ba8cb24e4..aae0a53e612 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -678,6 +678,16 @@ unsigned long arch_align_stack(unsigned long sp) unsigned long arch_randomize_brk(struct mm_struct *mm) { unsigned long range_end = mm->brk + 0x02000000; - return randomize_range(mm->brk, range_end, 0) ? : mm->brk; + unsigned long bump = 0; +#ifdef CONFIG_X86_32 + /* when using ASLR in arch_get_unmapped_exec_area, we must shove + the brk segment way out of the way of the exec area, since it + can collide with future allocations if not. */ + if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && + (mm->brk < 0x08000000) ) { + bump = (TASK_SIZE/6); + } +#endif + return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); } diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 1dab5194fd9..ff3a3bfdd64 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -131,6 +131,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm) } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; +#ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) + && !(__supported_pte_mask & _PAGE_NX) + && mmap_is_ia32()) + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; +#endif mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index 468d591dde3..df0ac0027b3 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -331,7 +331,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) if (compat) addr = VDSO_HIGH_BASE; else { - addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); + addr = get_unmapped_area_prot(NULL, 0, PAGE_SIZE, 0, 0, 1); if (IS_ERR_VALUE(addr)) { ret = addr; goto up_fail; |