2008-01-30 20:31:07 +08:00
|
|
|
/*
|
2008-01-30 20:31:10 +08:00
|
|
|
* Flexible mmap layout support
|
2008-01-30 20:31:07 +08:00
|
|
|
*
|
|
|
|
* Based on code by Ingo Molnar and Andi Kleen, copyrighted
|
|
|
|
* as follows:
|
|
|
|
*
|
2009-01-31 09:03:42 +08:00
|
|
|
* Copyright 2003-2009 Red Hat Inc.
|
2008-01-30 20:31:07 +08:00
|
|
|
* 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>
|
2009-09-08 17:01:55 +08:00
|
|
|
#include <asm/elf.h>
|
|
|
|
|
2014-09-06 07:16:45 +08:00
|
|
|
struct va_alignment __read_mostly va_align = {
|
2011-08-06 20:31:38 +08:00
|
|
|
.flags = -1,
|
|
|
|
};
|
|
|
|
|
2015-02-15 01:33:50 +08:00
|
|
|
static unsigned long stack_maxrandom_size(void)
|
2009-09-08 17:01:55 +08:00
|
|
|
{
|
2015-02-15 01:33:50 +08:00
|
|
|
unsigned long max = 0;
|
2009-09-08 17:01:55 +08:00
|
|
|
if ((current->flags & PF_RANDOMIZE) &&
|
|
|
|
!(current->personality & ADDR_NO_RANDOMIZE)) {
|
2015-02-15 01:33:50 +08:00
|
|
|
max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
|
2009-09-08 17:01:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
/*
|
|
|
|
* Top of mmap area (just below the process stack).
|
|
|
|
*
|
2009-09-08 17:01:55 +08:00
|
|
|
* Leave an at least ~128 MB hole with possible stack randomization.
|
2008-01-30 20:31:07 +08:00
|
|
|
*/
|
2009-09-08 17:01:55 +08:00
|
|
|
#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
|
2008-01-30 20:31:07 +08:00
|
|
|
#define MAX_GAP (TASK_SIZE/6*5)
|
2006-01-17 14:03:38 +08:00
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
static int mmap_is_legacy(void)
|
2008-01-30 20:31:07 +08:00
|
|
|
{
|
|
|
|
if (current->personality & ADDR_COMPAT_LAYOUT)
|
|
|
|
return 1;
|
|
|
|
|
2010-01-28 00:32:22 +08:00
|
|
|
if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
|
2008-01-30 20:31:07 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return sysctl_legacy_va_layout;
|
|
|
|
}
|
|
|
|
|
2015-04-15 06:48:00 +08:00
|
|
|
unsigned long arch_mmap_rnd(void)
|
2008-01-30 20:31:10 +08:00
|
|
|
{
|
2015-04-15 06:47:45 +08:00
|
|
|
unsigned long rnd;
|
2008-01-30 20:31:10 +08:00
|
|
|
|
2015-04-15 06:47:45 +08:00
|
|
|
if (mmap_is_ia32())
|
2016-01-15 07:20:06 +08:00
|
|
|
#ifdef CONFIG_COMPAT
|
2016-02-27 07:19:37 +08:00
|
|
|
rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
|
2016-01-15 07:20:06 +08:00
|
|
|
#else
|
2016-02-27 07:19:37 +08:00
|
|
|
rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
|
2016-01-15 07:20:06 +08:00
|
|
|
#endif
|
2015-04-15 06:47:45 +08:00
|
|
|
else
|
2016-02-27 07:19:37 +08:00
|
|
|
rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
|
2015-04-15 06:47:45 +08:00
|
|
|
|
2008-01-30 20:31:10 +08:00
|
|
|
return rnd << PAGE_SHIFT;
|
|
|
|
}
|
|
|
|
|
2015-04-15 06:47:45 +08:00
|
|
|
static unsigned long mmap_base(unsigned long rnd)
|
2008-01-30 20:31:10 +08:00
|
|
|
{
|
2010-01-28 00:32:22 +08:00
|
|
|
unsigned long gap = rlimit(RLIMIT_STACK);
|
2008-01-30 20:31:10 +08:00
|
|
|
|
|
|
|
if (gap < MIN_GAP)
|
|
|
|
gap = MIN_GAP;
|
|
|
|
else if (gap > MAX_GAP)
|
|
|
|
gap = MAX_GAP;
|
|
|
|
|
2015-04-15 06:47:45 +08:00
|
|
|
return PAGE_ALIGN(TASK_SIZE - gap - rnd);
|
2008-01-30 20:31:10 +08:00
|
|
|
}
|
|
|
|
|
2008-01-30 20:31:07 +08:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2015-04-15 06:47:45 +08:00
|
|
|
unsigned long random_factor = 0UL;
|
|
|
|
|
|
|
|
if (current->flags & PF_RANDOMIZE)
|
2015-04-15 06:48:00 +08:00
|
|
|
random_factor = arch_mmap_rnd();
|
2015-04-15 06:47:45 +08:00
|
|
|
|
x86/mm/32: Enable full randomization on i386 and X86_32
Currently on i386 and on X86_64 when emulating X86_32 in legacy mode, only
the stack and the executable are randomized but not other mmapped files
(libraries, vDSO, etc.). This patch enables randomization for the
libraries, vDSO and mmap requests on i386 and in X86_32 in legacy mode.
By default on i386 there are 8 bits for the randomization of the libraries,
vDSO and mmaps which only uses 1MB of VA.
This patch preserves the original randomness, using 1MB of VA out of 3GB or
4GB. We think that 1MB out of 3GB is not a big cost for having the ASLR.
The first obvious security benefit is that all objects are randomized (not
only the stack and the executable) in legacy mode which highly increases
the ASLR effectiveness, otherwise the attackers may use these
non-randomized areas. But also sensitive setuid/setgid applications are
more secure because currently, attackers can disable the randomization of
these applications by setting the ulimit stack to "unlimited". This is a
very old and widely known trick to disable the ASLR in i386 which has been
allowed for too long.
Another trick used to disable the ASLR was to set the ADDR_NO_RANDOMIZE
personality flag, but fortunately this doesn't work on setuid/setgid
applications because there is security checks which clear Security-relevant
flags.
This patch always randomizes the mmap_legacy_base address, removing the
possibility to disable the ASLR by setting the stack to "unlimited".
Signed-off-by: Hector Marco-Gisbert <hecmargi@upv.es>
Acked-by: Ismael Ripoll Ripoll <iripoll@upv.es>
Acked-by: Kees Cook <keescook@chromium.org>
Acked-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: akpm@linux-foundation.org
Cc: kees Cook <keescook@chromium.org>
Link: http://lkml.kernel.org/r/1457639460-5242-1-git-send-email-hecmargi@upv.es
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-03-11 03:51:00 +08:00
|
|
|
mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor;
|
2013-08-22 01:55:59 +08:00
|
|
|
|
2008-01-30 20:31:10 +08:00
|
|
|
if (mmap_is_legacy()) {
|
2013-08-22 01:55:59 +08:00
|
|
|
mm->mmap_base = mm->mmap_legacy_base;
|
2008-01-30 20:31:07 +08:00
|
|
|
mm->get_unmapped_area = arch_get_unmapped_area;
|
|
|
|
} else {
|
2015-04-15 06:47:45 +08:00
|
|
|
mm->mmap_base = mmap_base(random_factor);
|
2008-01-30 20:31:07 +08:00
|
|
|
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
|
|
|
}
|
2006-01-17 14:03:38 +08:00
|
|
|
}
|
2015-07-21 05:29:58 +08:00
|
|
|
|
|
|
|
const char *arch_vma_name(struct vm_area_struct *vma)
|
|
|
|
{
|
|
|
|
if (vma->vm_flags & VM_MPX)
|
|
|
|
return "[mpx]";
|
|
|
|
return NULL;
|
|
|
|
}
|