2008-01-30 20:31:07 +08:00
|
|
|
/*
|
|
|
|
* linux/arch/x86-64/mm/mmap.c
|
|
|
|
*
|
|
|
|
* flexible mmap layout support
|
|
|
|
*
|
|
|
|
* Based on code by Ingo Molnar and Andi Kleen, copyrighted
|
|
|
|
* as follows:
|
|
|
|
*
|
|
|
|
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Copyright 2005 Andi Kleen, SUSE Labs.
|
|
|
|
* Copyright 2007 Jiri Kosina, SUSE Labs.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
2006-01-17 14:03:38 +08:00
|
|
|
*/
|
2008-01-30 20:31:07 +08:00
|
|
|
|
|
|
|
#include <linux/personality.h>
|
2006-01-17 14:03:38 +08:00
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/random.h>
|
2008-01-30 20:31:07 +08:00
|
|
|
#include <linux/limits.h>
|
|
|
|
#include <linux/sched.h>
|
2006-01-17 14:03:38 +08:00
|
|
|
#include <asm/ia32.h>
|
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
/*
|
|
|
|
* Top of mmap area (just below the process stack).
|
|
|
|
*
|
|
|
|
* Leave an at least ~128 MB hole.
|
|
|
|
*/
|
|
|
|
#define MIN_GAP (128*1024*1024)
|
|
|
|
#define MAX_GAP (TASK_SIZE/6*5)
|
2006-01-17 14:03:38 +08:00
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
static inline unsigned long mmap_base(void)
|
|
|
|
{
|
|
|
|
unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
|
|
|
|
|
|
|
|
if (gap < MIN_GAP)
|
|
|
|
gap = MIN_GAP;
|
|
|
|
else if (gap > MAX_GAP)
|
|
|
|
gap = MAX_GAP;
|
|
|
|
|
|
|
|
return TASK_SIZE - (gap & PAGE_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int mmap_is_32(void)
|
2006-01-17 14:03:38 +08:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_IA32_EMULATION
|
2008-01-30 20:31:07 +08:00
|
|
|
if (test_thread_flag(TIF_IA32))
|
|
|
|
return 1;
|
2006-01-17 14:03:38 +08:00
|
|
|
#endif
|
2008-01-30 20:31:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int mmap_is_legacy(void)
|
|
|
|
{
|
|
|
|
if (current->personality & ADDR_COMPAT_LAYOUT)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return sysctl_legacy_va_layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function, called very early during the creation of a new
|
|
|
|
* process VM image, sets up which VM layout function to use:
|
|
|
|
*/
|
|
|
|
void arch_pick_mmap_layout(struct mm_struct *mm)
|
|
|
|
{
|
|
|
|
int rnd = 0;
|
2006-01-17 14:03:38 +08:00
|
|
|
if (current->flags & PF_RANDOMIZE) {
|
2008-01-30 20:30:25 +08:00
|
|
|
/*
|
2008-01-30 20:31:07 +08:00
|
|
|
* Add 28bit randomness which is about 40bits of address space
|
|
|
|
* because mmap base has to be page aligned.
|
|
|
|
* or ~1/128 of the total user VM
|
|
|
|
* (total user address space is 47bits)
|
2008-01-30 20:30:25 +08:00
|
|
|
*/
|
2008-01-30 20:31:07 +08:00
|
|
|
rnd = get_random_int() & 0xfffffff;
|
|
|
|
}
|
2008-01-30 20:30:25 +08:00
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
/*
|
|
|
|
* Fall back to the standard layout if the personality
|
|
|
|
* bit is set, or if the expected stack growth is unlimited:
|
|
|
|
*/
|
|
|
|
if (mmap_is_32()) {
|
|
|
|
#ifdef CONFIG_IA32_EMULATION
|
|
|
|
/* ia32_pick_mmap_layout has its own. */
|
|
|
|
return ia32_pick_mmap_layout(mm);
|
|
|
|
#endif
|
x86: PIE executable randomization, checkpatch fixes
#39: FILE: arch/ia64/ia32/binfmt_elf32.c:229:
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
WARNING: no space between function name and open parenthesis '('
#39: FILE: arch/ia64/ia32/binfmt_elf32.c:229:
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
WARNING: line over 80 characters
#67: FILE: arch/x86/kernel/sys_x86_64.c:80:
+ new_begin = randomize_range(*begin, *begin + 0x02000000, 0);
ERROR: use tabs not spaces
#110: FILE: arch/x86/kernel/sys_x86_64.c:185:
+ ^I mm->cached_hole_size = 0;$
ERROR: use tabs not spaces
#111: FILE: arch/x86/kernel/sys_x86_64.c:186:
+ ^I^Imm->free_area_cache = mm->mmap_base;$
ERROR: use tabs not spaces
#112: FILE: arch/x86/kernel/sys_x86_64.c:187:
+ ^I}$
ERROR: use tabs not spaces
#141: FILE: arch/x86/kernel/sys_x86_64.c:216:
+ ^I^I/* remember the largest hole we saw so far */$
ERROR: use tabs not spaces
#142: FILE: arch/x86/kernel/sys_x86_64.c:217:
+ ^I^Iif (addr + mm->cached_hole_size < vma->vm_start)$
ERROR: use tabs not spaces
#143: FILE: arch/x86/kernel/sys_x86_64.c:218:
+ ^I^I mm->cached_hole_size = vma->vm_start - addr;$
ERROR: use tabs not spaces
#157: FILE: arch/x86/kernel/sys_x86_64.c:232:
+ ^Imm->free_area_cache = TASK_UNMAPPED_BASE;$
ERROR: need a space before the open parenthesis '('
#291: FILE: arch/x86/mm/mmap_64.c:101:
+ } else if(mmap_is_legacy()) {
WARNING: braces {} are not necessary for single statement blocks
#302: FILE: arch/x86/mm/mmap_64.c:112:
+ if (current->flags & PF_RANDOMIZE) {
+ mm->mmap_base += ((long)rnd) << PAGE_SHIFT;
+ }
WARNING: line over 80 characters
#314: FILE: fs/binfmt_elf.c:48:
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
WARNING: no space between function name and open parenthesis '('
#314: FILE: fs/binfmt_elf.c:48:
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
WARNING: line over 80 characters
#429: FILE: fs/binfmt_elf.c:438:
+ eppnt, elf_prot, elf_type, total_size);
ERROR: need space after that ',' (ctx:VxV)
#480: FILE: fs/binfmt_elf.c:939:
+ elf_prot, elf_flags,0);
^
total: 9 errors, 7 warnings, 461 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Please run checkpatch prior to sending patches
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Jakub Jelinek <jakub@redhat.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-01-30 20:31:07 +08:00
|
|
|
} else if (mmap_is_legacy()) {
|
2008-01-30 20:31:07 +08:00
|
|
|
mm->mmap_base = TASK_UNMAPPED_BASE;
|
|
|
|
mm->get_unmapped_area = arch_get_unmapped_area;
|
|
|
|
mm->unmap_area = arch_unmap_area;
|
|
|
|
} else {
|
|
|
|
mm->mmap_base = mmap_base();
|
|
|
|
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
|
|
|
mm->unmap_area = arch_unmap_area_topdown;
|
|
|
|
if (current->flags & PF_RANDOMIZE)
|
|
|
|
rnd = -rnd;
|
|
|
|
}
|
x86: PIE executable randomization, checkpatch fixes
#39: FILE: arch/ia64/ia32/binfmt_elf32.c:229:
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
WARNING: no space between function name and open parenthesis '('
#39: FILE: arch/ia64/ia32/binfmt_elf32.c:229:
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
WARNING: line over 80 characters
#67: FILE: arch/x86/kernel/sys_x86_64.c:80:
+ new_begin = randomize_range(*begin, *begin + 0x02000000, 0);
ERROR: use tabs not spaces
#110: FILE: arch/x86/kernel/sys_x86_64.c:185:
+ ^I mm->cached_hole_size = 0;$
ERROR: use tabs not spaces
#111: FILE: arch/x86/kernel/sys_x86_64.c:186:
+ ^I^Imm->free_area_cache = mm->mmap_base;$
ERROR: use tabs not spaces
#112: FILE: arch/x86/kernel/sys_x86_64.c:187:
+ ^I}$
ERROR: use tabs not spaces
#141: FILE: arch/x86/kernel/sys_x86_64.c:216:
+ ^I^I/* remember the largest hole we saw so far */$
ERROR: use tabs not spaces
#142: FILE: arch/x86/kernel/sys_x86_64.c:217:
+ ^I^Iif (addr + mm->cached_hole_size < vma->vm_start)$
ERROR: use tabs not spaces
#143: FILE: arch/x86/kernel/sys_x86_64.c:218:
+ ^I^I mm->cached_hole_size = vma->vm_start - addr;$
ERROR: use tabs not spaces
#157: FILE: arch/x86/kernel/sys_x86_64.c:232:
+ ^Imm->free_area_cache = TASK_UNMAPPED_BASE;$
ERROR: need a space before the open parenthesis '('
#291: FILE: arch/x86/mm/mmap_64.c:101:
+ } else if(mmap_is_legacy()) {
WARNING: braces {} are not necessary for single statement blocks
#302: FILE: arch/x86/mm/mmap_64.c:112:
+ if (current->flags & PF_RANDOMIZE) {
+ mm->mmap_base += ((long)rnd) << PAGE_SHIFT;
+ }
WARNING: line over 80 characters
#314: FILE: fs/binfmt_elf.c:48:
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
WARNING: no space between function name and open parenthesis '('
#314: FILE: fs/binfmt_elf.c:48:
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
WARNING: line over 80 characters
#429: FILE: fs/binfmt_elf.c:438:
+ eppnt, elf_prot, elf_type, total_size);
ERROR: need space after that ',' (ctx:VxV)
#480: FILE: fs/binfmt_elf.c:939:
+ elf_prot, elf_flags,0);
^
total: 9 errors, 7 warnings, 461 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Please run checkpatch prior to sending patches
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Jakub Jelinek <jakub@redhat.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-01-30 20:31:07 +08:00
|
|
|
if (current->flags & PF_RANDOMIZE)
|
2008-01-30 20:31:07 +08:00
|
|
|
mm->mmap_base += ((long)rnd) << PAGE_SHIFT;
|
2006-01-17 14:03:38 +08:00
|
|
|
}
|