[PATCH] x86_64: Flexmap for 32bit and randomized mappings for 64bit

Another try at this.

For 32bit follow the 32bit implementation from Ingo -
mappings are growing down from the end of stack now
and vary randomly by 1GB.

Randomized mappings for 64bit just vary the normal mmap break
by 1TB. I didn't bother implementing full flex mmap for 64bit
because it shouldn't be needed there.

Cc: mingo@elte.hu

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Andi Kleen and committed by Linus Torvalds 8817210d 562795fe

+115 -2
+2 -1
arch/x86_64/ia32/Makefile
··· 3 # 4 5 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ 6 - ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o 7 8 sysv-$(CONFIG_SYSVIPC) := ipc32.o 9 obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
··· 3 # 4 5 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ 6 + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \ 7 + mmap32.o 8 9 sysv-$(CONFIG_SYSVIPC) := ipc32.o 10 obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
+78
arch/x86_64/ia32/mmap32.c
···
··· 1 + /* 2 + * linux/arch/x86_64/ia32/mm/mmap.c 3 + * 4 + * flexible mmap layout support 5 + * 6 + * Based on the i386 version which was 7 + * 8 + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 9 + * All Rights Reserved. 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this program; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + * 26 + * Started by Ingo Molnar <mingo@elte.hu> 27 + */ 28 + 29 + #include <linux/personality.h> 30 + #include <linux/mm.h> 31 + #include <linux/random.h> 32 + 33 + /* 34 + * Top of mmap area (just below the process stack). 35 + * 36 + * Leave an at least ~128 MB hole. 37 + */ 38 + #define MIN_GAP (128*1024*1024) 39 + #define MAX_GAP (TASK_SIZE/6*5) 40 + 41 + static inline unsigned long mmap_base(struct mm_struct *mm) 42 + { 43 + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; 44 + unsigned long random_factor = 0; 45 + 46 + if (current->flags & PF_RANDOMIZE) 47 + random_factor = get_random_int() % (1024*1024); 48 + 49 + if (gap < MIN_GAP) 50 + gap = MIN_GAP; 51 + else if (gap > MAX_GAP) 52 + gap = MAX_GAP; 53 + 54 + return PAGE_ALIGN(TASK_SIZE - gap - random_factor); 55 + } 56 + 57 + /* 58 + * This function, called very early during the creation of a new 59 + * process VM image, sets up which VM layout function to use: 60 + */ 61 + void ia32_pick_mmap_layout(struct mm_struct *mm) 62 + { 63 + /* 64 + * Fall back to the standard layout if the personality 65 + * bit is set, or if the expected stack growth is unlimited: 66 + */ 67 + if (sysctl_legacy_va_layout || 68 + (current->personality & ADDR_COMPAT_LAYOUT) || 69 + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { 70 + mm->mmap_base = TASK_UNMAPPED_BASE; 71 + mm->get_unmapped_area = arch_get_unmapped_area; 72 + mm->unmap_area = arch_unmap_area; 73 + } else { 74 + mm->mmap_base = mmap_base(mm); 75 + mm->get_unmapped_area = arch_get_unmapped_area_topdown; 76 + mm->unmap_area = arch_unmap_area_topdown; 77 + } 78 + }
+1 -1
arch/x86_64/mm/Makefile
··· 2 # Makefile for the linux x86_64-specific parts of the memory manager. 3 # 4 5 - obj-y := init.o fault.o ioremap.o extable.o pageattr.o 6 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 7 obj-$(CONFIG_NUMA) += numa.o 8 obj-$(CONFIG_K8_NUMA) += k8topology.o
··· 2 # Makefile for the linux x86_64-specific parts of the memory manager. 3 # 4 5 + obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o 6 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 7 obj-$(CONFIG_NUMA) += numa.o 8 obj-$(CONFIG_K8_NUMA) += k8topology.o
+30
arch/x86_64/mm/mmap.c
···
··· 1 + /* Copyright 2005 Andi Kleen, SuSE Labs. 2 + * Licensed under GPL, v.2 3 + */ 4 + #include <linux/config.h> 5 + #include <linux/mm.h> 6 + #include <linux/sched.h> 7 + #include <linux/random.h> 8 + #include <asm/ia32.h> 9 + 10 + /* Notebook: move the mmap code from sys_x86_64.c over here. */ 11 + 12 + void arch_pick_mmap_layout(struct mm_struct *mm) 13 + { 14 + #ifdef CONFIG_IA32_EMULATION 15 + if (current_thread_info()->flags & _TIF_IA32) 16 + return ia32_pick_mmap_layout(mm); 17 + #endif 18 + mm->mmap_base = TASK_UNMAPPED_BASE; 19 + if (current->flags & PF_RANDOMIZE) { 20 + /* Add 28bit randomness which is about 40bits of address space 21 + because mmap base has to be page aligned. 22 + or ~1/128 of the total user VM 23 + (total user address space is 47bits) */ 24 + unsigned rnd = get_random_int() & 0xfffffff; 25 + mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; 26 + } 27 + mm->get_unmapped_area = arch_get_unmapped_area; 28 + mm->unmap_area = arch_unmap_area; 29 + } 30 +
+2
include/asm-x86_64/ia32.h
··· 169 struct linux_binprm; 170 extern int ia32_setup_arg_pages(struct linux_binprm *bprm, 171 unsigned long stack_top, int exec_stack); 172 173 #endif 174
··· 169 struct linux_binprm; 170 extern int ia32_setup_arg_pages(struct linux_binprm *bprm, 171 unsigned long stack_top, int exec_stack); 172 + struct mm_struct; 173 + extern void ia32_pick_mmap_layout(struct mm_struct *mm); 174 175 #endif 176
+2
include/asm-x86_64/processor.h
··· 477 /* Boot loader type from the setup header */ 478 extern int bootloader_type; 479 480 #endif /* __ASM_X86_64_PROCESSOR_H */
··· 477 /* Boot loader type from the setup header */ 478 extern int bootloader_type; 479 480 + #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 481 + 482 #endif /* __ASM_X86_64_PROCESSOR_H */