x86: randomize brk
authorJiri Kosina <jkosina@suse.cz>
Wed, 30 Jan 2008 12:30:40 +0000 (13:30 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 30 Jan 2008 12:30:40 +0000 (13:30 +0100)
Randomize the location of the heap (brk) for i386 and x86_64.  The range is
randomized in the range starting at current brk location up to 0x02000000
offset for both architectures.  This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

Arjan says:

This is known to break older versions of some emacs variants, whose dumper
code assumed that the last variable declared in the program is equal to the
start of the dynamically allocated memory region.

(The dumper is the code where emacs effectively dumps core at the end of it's
compilation stage; this coredump is then loaded as the main program during
normal use)

iirc this was 5 years or so; we found this way back when I was at RH and we
first did the security stuff there (including this brk randomization).  It
wasn't all variants of emacs, and it got fixed as a result (I vaguely remember
that emacs already had code to deal with it for other archs/oses, just
ifdeffed wrongly).

It's a rare and wrong assumption as a general thing, just on x86 it mostly
happened to be true (but to be honest, it'll break too if gcc does
something fancy or if the linker does a non-standard order).  Still its
something we should at least document.

Note 2: afaik it only broke the emacs *build*.  I'm not 100% sure about that
(it IS 5 years ago) though.

[ akpm@linux-foundation.org: deuglification ]

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Roland McGrath <roland@redhat.com>
Cc: Jakub Jelinek <jakub@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>
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
fs/binfmt_elf.c
include/asm-x86/elf.h
mm/mmap.c

index a8cdd09ad53fb753fb0f7d04a44dec1c63d96ed1..631af167bc51c376c38571518799a38d0e77c6bf 100644 (file)
@@ -992,3 +992,10 @@ unsigned long arch_align_stack(unsigned long sp)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+       unsigned long range_end = mm->brk + 0x02000000;
+       return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
index 98d85952f57491ddfb8beb43d24f2f6a30baae74..aa9414ed74c75e1a1dbc1b3623ff343389e41ea6 100644 (file)
@@ -914,3 +914,10 @@ unsigned long arch_align_stack(unsigned long sp)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+       unsigned long range_end = mm->brk + 0x02000000;
+       return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
index f0b3171842f22e75796d2aa68a7713f30af2f111..043a800c8f71fa1f68466e46c693045be6d6802b 100644 (file)
@@ -1021,6 +1021,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        current->mm->end_data = end_data;
        current->mm->start_stack = bprm->p;
 
+#ifdef arch_randomize_brk
+       if (current->flags & PF_RANDOMIZE)
+               current->mm->brk = current->mm->start_brk =
+                       arch_randomize_brk(current->mm);
+#endif
+
        if (current->personality & MMAP_PAGE_ZERO) {
                /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
                   and some applications "depend" upon this behavior.
index ec42a4d2e83b1ab60ab3e24e8fe0732a8431ee4c..cd3204ebbbdda8b259bfb35bcd104f25574ec6f8 100644 (file)
@@ -285,6 +285,9 @@ struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                       int executable_stack);
 
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
 #endif /* __KERNEL__ */
 
 #endif
index bfa389fc6ded6a2a5892eec57ed6cd90bbd34d1e..d2b6d44962b7c7b28b89e20cdbf1af0b0c6ada31 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -251,7 +251,8 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
         * not page aligned -Ram Gupta
         */
        rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
-       if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+       if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
+                       (mm->end_data - mm->start_data) > rlim)
                goto out;
 
        newbrk = PAGE_ALIGN(brk);