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