Commit ba455d81 authored by Hector Marco-Gisbert's avatar Hector Marco-Gisbert Committed by Willy Tarreau

ASLR: fix stack randomization on 64-bit systems

commit 4e7c22d4 upstream

The issue is that the stack for processes is not properly randomized on 64 bit
architectures due to an integer overflow.

The affected function is randomize_stack_top() in file "fs/binfmt_elf.c":

static unsigned long randomize_stack_top(unsigned long stack_top)
{
         unsigned int random_variable = 0;

         if ((current->flags & PF_RANDOMIZE) &&
                 !(current->personality & ADDR_NO_RANDOMIZE)) {
                 random_variable = get_random_int() & STACK_RND_MASK;
                 random_variable <<= PAGE_SHIFT;
         }
         return PAGE_ALIGN(stack_top) + random_variable;
         return PAGE_ALIGN(stack_top) - random_variable;
}

Note that, it declares the "random_variable" variable as "unsigned int". Since
the result of the shifting operation between STACK_RND_MASK (which is
0x3fffff on x86_64, 22 bits) and PAGE_SHIFT (which is 12 on x86_64):

random_variable <<= PAGE_SHIFT;

then the two leftmost bits are dropped when storing the result in the
"random_variable". This variable shall be at least 34 bits long to hold the
(22+12) result.

These two dropped bits have an impact on the entropy of process stack.
Concretely, the total stack entropy is reduced by four: from 2^28 to 2^30 (One
fourth of expected entropy).

This patch restores back the entropy by correcting the types involved in the
operations in the functions randomize_stack_top() and stack_maxrandom_size().

The successful fix can be tested with:
$ for i in `seq 1 10`; do cat /proc/self/maps | grep stack; done
7ffeda566000-7ffeda587000 rw-p 00000000 00:00 0                          [stack]
7fff5a332000-7fff5a353000 rw-p 00000000 00:00 0                          [stack]
7ffcdb7a1000-7ffcdb7c2000 rw-p 00000000 00:00 0                          [stack]
7ffd5e2c4000-7ffd5e2e5000 rw-p 00000000 00:00 0                          [stack]
...

Once corrected, the leading bytes should be between 7ffc and 7fff, rather
than always being 7fff.

CVE-2015-1593
Signed-off-by: default avatarHector Marco-Gisbert <hecmargi@upv.es>
Signed-off-by: default avatarIsmael Ripoll <iripoll@upv.es>
[kees: rebase, fix 80 char, clean up commit message, add test example, cve]
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
parent 7f36f1ac
......@@ -31,12 +31,12 @@
#include <linux/sched.h>
#include <asm/elf.h>
static unsigned int stack_maxrandom_size(void)
static unsigned long stack_maxrandom_size(void)
{
unsigned int max = 0;
unsigned long max = 0;
if ((current->flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT;
max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
}
return max;
......
......@@ -546,11 +546,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
static unsigned long randomize_stack_top(unsigned long stack_top)
{
unsigned int random_variable = 0;
unsigned long random_variable = 0;
if ((current->flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
random_variable = get_random_int() & STACK_RND_MASK;
random_variable = (unsigned long) get_random_int();
random_variable &= STACK_RND_MASK;
random_variable <<= PAGE_SHIFT;
}
#ifdef CONFIG_STACK_GROWSUP
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment