summaryrefslogtreecommitdiffstats
path: root/setup_arg_pages-diagnose-excessive-argument-size.patch
diff options
context:
space:
mode:
Diffstat (limited to 'setup_arg_pages-diagnose-excessive-argument-size.patch')
-rw-r--r--setup_arg_pages-diagnose-excessive-argument-size.patch42
1 files changed, 42 insertions, 0 deletions
diff --git a/setup_arg_pages-diagnose-excessive-argument-size.patch b/setup_arg_pages-diagnose-excessive-argument-size.patch
new file mode 100644
index 0000000..ead972a
--- /dev/null
+++ b/setup_arg_pages-diagnose-excessive-argument-size.patch
@@ -0,0 +1,42 @@
+From: Roland McGrath <roland@redhat.com>
+Date: Wed, 8 Sep 2010 02:35:49 +0000 (-0700)
+Subject: setup_arg_pages: diagnose excessive argument size
+X-Git-Tag: v2.6.36-rc4~14
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=1b528181b2ffa14721fb28ad1bd539fe1732c583
+
+setup_arg_pages: diagnose excessive argument size
+
+The CONFIG_STACK_GROWSDOWN variant of setup_arg_pages() does not
+check the size of the argument/environment area on the stack.
+When it is unworkably large, shift_arg_pages() hits its BUG_ON.
+This is exploitable with a very large RLIMIT_STACK limit, to
+create a crash pretty easily.
+
+Check that the initial stack is not too large to make it possible
+to map in any executable. We're not checking that the actual
+executable (or intepreter, for binfmt_elf) will fit. So those
+mappings might clobber part of the initial stack mapping. But
+that is just userland lossage that userland made happen, not a
+kernel problem.
+
+Signed-off-by: Roland McGrath <roland@redhat.com>
+Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+---
+
+diff --git a/fs/exec.c b/fs/exec.c
+index 2d94552..1b63237 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -594,6 +594,11 @@ int setup_arg_pages(struct linux_binprm *bprm,
+ #else
+ stack_top = arch_align_stack(stack_top);
+ stack_top = PAGE_ALIGN(stack_top);
++
++ if (unlikely(stack_top < mmap_min_addr) ||
++ unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
++ return -ENOMEM;
++
+ stack_shift = vma->vm_end - stack_top;
+
+ bprm->p -= stack_shift;