1 From d045c77c1a69703143a36169c224429c48b9eecd Mon Sep 17 00:00:00 2001
2 From: Helge Deller <deller@gmx.de>
3 Date: Mon, 11 May 2015 22:01:27 +0200
4 Subject: parisc,metag: Fix crashes due to stack randomization on stack-grows-upwards architectures
6 From: Helge Deller <deller@gmx.de>
8 commit d045c77c1a69703143a36169c224429c48b9eecd upstream.
10 On architectures where the stack grows upwards (CONFIG_STACK_GROWSUP=y,
11 currently parisc and metag only) stack randomization sometimes leads to crashes
12 when the stack ulimit is set to lower values than STACK_RND_MASK (which is 8 MB
13 by default if not defined in arch-specific headers).
15 The problem is, that when the stack vm_area_struct is set up in fs/exec.c, the
16 additional space needed for the stack randomization (as defined by the value of
17 STACK_RND_MASK) was not taken into account yet and as such, when the stack
18 randomization code added a random offset to the stack start, the stack
19 effectively got smaller than what the user defined via rlimit_max(RLIMIT_STACK)
20 which then sometimes leads to out-of-stack situations and crashes.
22 This patch fixes it by adding the maximum possible amount of memory (based on
23 STACK_RND_MASK) which theoretically could be added by the stack randomization
24 code to the initial stack size. That way, the user-defined stack size is always
25 guaranteed to be at minimum what is defined via rlimit_max(RLIMIT_STACK).
27 This bug is currently not visible on the metag architecture, because on metag
28 STACK_RND_MASK is defined to 0 which effectively disables stack randomization.
30 The changes to fs/exec.c are inside an "#ifdef CONFIG_STACK_GROWSUP"
31 section, so it does not affect other platformws beside those where the
32 stack grows upwards (parisc and metag).
34 Signed-off-by: Helge Deller <deller@gmx.de>
35 Cc: linux-parisc@vger.kernel.org
36 Cc: James Hogan <james.hogan@imgtec.com>
37 Cc: linux-metag@vger.kernel.org
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41 arch/parisc/include/asm/elf.h | 4 ++++
42 arch/parisc/kernel/sys_parisc.c | 3 +++
44 3 files changed, 10 insertions(+)
46 --- a/arch/parisc/include/asm/elf.h
47 +++ b/arch/parisc/include/asm/elf.h
48 @@ -348,6 +348,10 @@ struct pt_regs; /* forward declaration..
52 +#define STACK_RND_MASK (is_32bit_task() ? \
53 + 0x7ff >> (PAGE_SHIFT - 12) : \
54 + 0x3ffff >> (PAGE_SHIFT - 12))
57 extern unsigned long arch_randomize_brk(struct mm_struct *);
58 #define arch_randomize_brk arch_randomize_brk
59 --- a/arch/parisc/kernel/sys_parisc.c
60 +++ b/arch/parisc/kernel/sys_parisc.c
61 @@ -77,6 +77,9 @@ static unsigned long mmap_upper_limit(vo
62 if (stack_base > STACK_SIZE_MAX)
63 stack_base = STACK_SIZE_MAX;
65 + /* Add space for stack randomization. */
66 + stack_base += (STACK_RND_MASK << PAGE_SHIFT);
68 return PAGE_ALIGN(STACK_TOP - stack_base);
73 @@ -659,6 +659,9 @@ int setup_arg_pages(struct linux_binprm
74 if (stack_base > STACK_SIZE_MAX)
75 stack_base = STACK_SIZE_MAX;
77 + /* Add space for stack randomization. */
78 + stack_base += (STACK_RND_MASK << PAGE_SHIFT);
80 /* Make sure we didn't let the argument array grow too large. */
81 if (vma->vm_end - vma->vm_start > stack_base)