aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2015-05-11 16:01:27 -0400
committerHelge Deller <deller@gmx.de>2015-05-12 16:03:44 -0400
commitd045c77c1a69703143a36169c224429c48b9eecd (patch)
treef71e78b7585011274db82483cd95718e11171277
parent5fec97d0e3d93717f1d6a958a03e579078088861 (diff)
parisc,metag: Fix crashes due to stack randomization on stack-grows-upwards architectures
On architectures where the stack grows upwards (CONFIG_STACK_GROWSUP=y, currently parisc and metag only) stack randomization sometimes leads to crashes when the stack ulimit is set to lower values than STACK_RND_MASK (which is 8 MB by default if not defined in arch-specific headers). The problem is, that when the stack vm_area_struct is set up in fs/exec.c, the additional space needed for the stack randomization (as defined by the value of STACK_RND_MASK) was not taken into account yet and as such, when the stack randomization code added a random offset to the stack start, the stack effectively got smaller than what the user defined via rlimit_max(RLIMIT_STACK) which then sometimes leads to out-of-stack situations and crashes. This patch fixes it by adding the maximum possible amount of memory (based on STACK_RND_MASK) which theoretically could be added by the stack randomization code to the initial stack size. That way, the user-defined stack size is always guaranteed to be at minimum what is defined via rlimit_max(RLIMIT_STACK). This bug is currently not visible on the metag architecture, because on metag STACK_RND_MASK is defined to 0 which effectively disables stack randomization. The changes to fs/exec.c are inside an "#ifdef CONFIG_STACK_GROWSUP" section, so it does not affect other platformws beside those where the stack grows upwards (parisc and metag). Signed-off-by: Helge Deller <deller@gmx.de> Cc: linux-parisc@vger.kernel.org Cc: James Hogan <james.hogan@imgtec.com> Cc: linux-metag@vger.kernel.org Cc: stable@vger.kernel.org # v3.16+
-rw-r--r--arch/parisc/include/asm/elf.h4
-rw-r--r--arch/parisc/kernel/sys_parisc.c3
-rw-r--r--fs/exec.c3
3 files changed, 10 insertions, 0 deletions
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h
index 3391d061eccc..78c9fd32c554 100644
--- a/arch/parisc/include/asm/elf.h
+++ b/arch/parisc/include/asm/elf.h
@@ -348,6 +348,10 @@ struct pt_regs; /* forward declaration... */
348 348
349#define ELF_HWCAP 0 349#define ELF_HWCAP 0
350 350
351#define STACK_RND_MASK (is_32bit_task() ? \
352 0x7ff >> (PAGE_SHIFT - 12) : \
353 0x3ffff >> (PAGE_SHIFT - 12))
354
351struct mm_struct; 355struct mm_struct;
352extern unsigned long arch_randomize_brk(struct mm_struct *); 356extern unsigned long arch_randomize_brk(struct mm_struct *);
353#define arch_randomize_brk arch_randomize_brk 357#define arch_randomize_brk arch_randomize_brk
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index e1ffea2f9a0b..5aba01ac457f 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -77,6 +77,9 @@ static unsigned long mmap_upper_limit(void)
77 if (stack_base > STACK_SIZE_MAX) 77 if (stack_base > STACK_SIZE_MAX)
78 stack_base = STACK_SIZE_MAX; 78 stack_base = STACK_SIZE_MAX;
79 79
80 /* Add space for stack randomization. */
81 stack_base += (STACK_RND_MASK << PAGE_SHIFT);
82
80 return PAGE_ALIGN(STACK_TOP - stack_base); 83 return PAGE_ALIGN(STACK_TOP - stack_base);
81} 84}
82 85
diff --git a/fs/exec.c b/fs/exec.c
index 49a1c61433b7..1977c2a553ac 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -659,6 +659,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
659 if (stack_base > STACK_SIZE_MAX) 659 if (stack_base > STACK_SIZE_MAX)
660 stack_base = STACK_SIZE_MAX; 660 stack_base = STACK_SIZE_MAX;
661 661
662 /* Add space for stack randomization. */
663 stack_base += (STACK_RND_MASK << PAGE_SHIFT);
664
662 /* Make sure we didn't let the argument array grow too large. */ 665 /* Make sure we didn't let the argument array grow too large. */
663 if (vma->vm_end - vma->vm_start > stack_base) 666 if (vma->vm_end - vma->vm_start > stack_base)
664 return -ENOMEM; 667 return -ENOMEM;