aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2008-01-30 07:30:40 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:30:40 -0500
commitc1d171a002942ea2d93b4fbd0c9583c56fce0772 (patch)
tree49249c927dc1644e7c92150808269cb474bdd411
parent7b83dae7aa31db4f6d6e78c3c6d490a7ac58699c (diff)
x86: randomize brk
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>
-rw-r--r--arch/x86/kernel/process_32.c7
-rw-r--r--arch/x86/kernel/process_64.c7
-rw-r--r--fs/binfmt_elf.c6
-rw-r--r--include/asm-x86/elf.h3
-rw-r--r--mm/mmap.c3
5 files changed, 25 insertions, 1 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index a8cdd09ad53f..631af167bc51 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -992,3 +992,10 @@ unsigned long arch_align_stack(unsigned long sp)
992 sp -= get_random_int() % 8192; 992 sp -= get_random_int() % 8192;
993 return sp & ~0xf; 993 return sp & ~0xf;
994} 994}
995
996unsigned long arch_randomize_brk(struct mm_struct *mm)
997{
998 unsigned long range_end = mm->brk + 0x02000000;
999 return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
1000}
1001
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 98d85952f574..aa9414ed74c7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -914,3 +914,10 @@ unsigned long arch_align_stack(unsigned long sp)
914 sp -= get_random_int() % 8192; 914 sp -= get_random_int() % 8192;
915 return sp & ~0xf; 915 return sp & ~0xf;
916} 916}
917
918unsigned long arch_randomize_brk(struct mm_struct *mm)
919{
920 unsigned long range_end = mm->brk + 0x02000000;
921 return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
922}
923
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index f0b3171842f2..043a800c8f71 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1021,6 +1021,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1021 current->mm->end_data = end_data; 1021 current->mm->end_data = end_data;
1022 current->mm->start_stack = bprm->p; 1022 current->mm->start_stack = bprm->p;
1023 1023
1024#ifdef arch_randomize_brk
1025 if (current->flags & PF_RANDOMIZE)
1026 current->mm->brk = current->mm->start_brk =
1027 arch_randomize_brk(current->mm);
1028#endif
1029
1024 if (current->personality & MMAP_PAGE_ZERO) { 1030 if (current->personality & MMAP_PAGE_ZERO) {
1025 /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 1031 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1026 and some applications "depend" upon this behavior. 1032 and some applications "depend" upon this behavior.
diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h
index ec42a4d2e83b..cd3204ebbbdd 100644
--- a/include/asm-x86/elf.h
+++ b/include/asm-x86/elf.h
@@ -285,6 +285,9 @@ struct linux_binprm;
285extern int arch_setup_additional_pages(struct linux_binprm *bprm, 285extern int arch_setup_additional_pages(struct linux_binprm *bprm,
286 int executable_stack); 286 int executable_stack);
287 287
288extern unsigned long arch_randomize_brk(struct mm_struct *mm);
289#define arch_randomize_brk arch_randomize_brk
290
288#endif /* __KERNEL__ */ 291#endif /* __KERNEL__ */
289 292
290#endif 293#endif
diff --git a/mm/mmap.c b/mm/mmap.c
index bfa389fc6ded..d2b6d44962b7 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -251,7 +251,8 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
251 * not page aligned -Ram Gupta 251 * not page aligned -Ram Gupta
252 */ 252 */
253 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; 253 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
254 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim) 254 if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
255 (mm->end_data - mm->start_data) > rlim)
255 goto out; 256 goto out;
256 257
257 newbrk = PAGE_ALIGN(brk); 258 newbrk = PAGE_ALIGN(brk);