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