-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
main executable of (specially compiled/linked -pie/-fpie) ET_DYN binaries onto a random address (in cases in which mmap() is allowed to perform a randomization). The code has been extraced from Ingo's exec-shield patch http://people.redhat.com/mingo/exec-shield/ [akpm@linux-foundation.org: fix used-uninitialsied warning] [kamezawa.hiroyu@jp.fujitsu.com: fixed ia32 ELF on x86_64 handling] Signed-off-by: Jiri Kosina <jkosina@suse.cz> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Arjan van de Ven <arjan@infradead.org> Cc: Roland McGrath <roland@redhat.com> Cc: Jakub Jelinek <jakub@redhat.com> Cc: "Luck, Tony" <tony.luck@intel.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>
- Loading branch information
Jiri Kosina
authored and
Ingo Molnar
committed
Jan 30, 2008
1 parent
82f74e7
commit cc503c1
Showing
5 changed files
with
287 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,117 @@ | ||
/* Copyright 2005 Andi Kleen, SuSE Labs. | ||
* Licensed under GPL, v.2 | ||
/* | ||
* 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 | ||
* | ||
*/ | ||
|
||
#include <linux/personality.h> | ||
#include <linux/mm.h> | ||
#include <linux/sched.h> | ||
#include <linux/random.h> | ||
#include <linux/limits.h> | ||
#include <linux/sched.h> | ||
#include <asm/ia32.h> | ||
|
||
/* Notebook: move the mmap code from sys_x86_64.c over here. */ | ||
/* | ||
* 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) | ||
|
||
void arch_pick_mmap_layout(struct mm_struct *mm) | ||
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) | ||
{ | ||
#ifdef CONFIG_IA32_EMULATION | ||
if (current_thread_info()->flags & _TIF_IA32) | ||
return ia32_pick_mmap_layout(mm); | ||
if (test_thread_flag(TIF_IA32)) | ||
return 1; | ||
#endif | ||
mm->mmap_base = TASK_UNMAPPED_BASE; | ||
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; | ||
if (current->flags & PF_RANDOMIZE) { | ||
/* | ||
* 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) | ||
* 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) | ||
*/ | ||
unsigned rnd = get_random_int() & 0xfffffff; | ||
rnd = get_random_int() & 0xfffffff; | ||
} | ||
|
||
mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; | ||
/* | ||
* 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 | ||
} else if(mmap_is_legacy()) { | ||
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; | ||
} | ||
if (current->flags & PF_RANDOMIZE) { | ||
mm->mmap_base += ((long)rnd) << PAGE_SHIFT; | ||
} | ||
mm->get_unmapped_area = arch_get_unmapped_area; | ||
mm->unmap_area = arch_unmap_area; | ||
} | ||
|
Oops, something went wrong.