--- /dev/null
+From 803bf5ec259941936262d10ecc84511b76a20921 Mon Sep 17 00:00:00 2001
+From: Michael Neuling <mikey@neuling.org>
+Date: Wed, 10 Feb 2010 13:56:42 -0800
+Subject: fs/exec.c: restrict initial stack space expansion to rlimit
+
+From: Michael Neuling <mikey@neuling.org>
+
+commit 803bf5ec259941936262d10ecc84511b76a20921 upstream.
+
+When reserving stack space for a new process, make sure we're not
+attempting to expand the stack by more than rlimit allows.
+
+This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba ("mm:
+variable length argument support") and unmasked by
+fc63cf237078c86214abcb2ee9926d8ad289da9b ("exec: setup_arg_pages() fails
+to return errors").
+
+This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg.
+80K on 4K pages or 'ulimit -s 79') all processes will be killed before
+they start. This is particularly bad with 64K pages, where a ulimit below
+1280K will kill every process.
+
+To test, do:
+
+ 'ulimit -s 15; ls'
+
+before and after the patch is applied. Before it's applied, 'ls' should
+be killed. After the patch is applied, 'ls' should no longer be killed.
+
+A stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE.
+Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle
+correctly with this code.
+
+4K pages should be fine to test with.
+
+[kosaki.motohiro@jp.fujitsu.com: cleanup]
+[akpm@linux-foundation.org: cleanup cleanup]
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Americo Wang <xiyou.wangcong@gmail.com>
+Cc: Anton Blanchard <anton@samba.org>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Cc: James Morris <jmorris@namei.org>
+Cc: Ingo Molnar <mingo@elte.hu>
+Cc: Serge Hallyn <serue@us.ibm.com>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/exec.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -589,6 +589,9 @@ int setup_arg_pages(struct linux_binprm
+ struct vm_area_struct *prev = NULL;
+ unsigned long vm_flags;
+ unsigned long stack_base;
++ unsigned long stack_size;
++ unsigned long stack_expand;
++ unsigned long rlim_stack;
+
+ #ifdef CONFIG_STACK_GROWSUP
+ /* Limit stack size to 1GB */
+@@ -647,10 +650,24 @@ int setup_arg_pages(struct linux_binprm
+ }
+ }
+
++ stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
++ stack_size = vma->vm_end - vma->vm_start;
++ /*
++ * Align this down to a page boundary as expand_stack
++ * will align it up.
++ */
++ rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
++ rlim_stack = min(rlim_stack, stack_size);
+ #ifdef CONFIG_STACK_GROWSUP
+- stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
++ if (stack_size + stack_expand > rlim_stack)
++ stack_base = vma->vm_start + rlim_stack;
++ else
++ stack_base = vma->vm_end + stack_expand;
+ #else
+- stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
++ if (stack_size + stack_expand > rlim_stack)
++ stack_base = vma->vm_end - rlim_stack;
++ else
++ stack_base = vma->vm_start - stack_expand;
+ #endif
+ ret = expand_stack(vma, stack_base);
+ if (ret)
--- /dev/null
+From 3e10e716abf3c71bdb5d86b8f507f9e72236c9cd Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Thu, 19 Nov 2009 17:16:37 +0100
+Subject: resource: add helpers for fetching rlimits
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 3e10e716abf3c71bdb5d86b8f507f9e72236c9cd upstream.
+
+We want to be sure that compiler fetches the limit variable only
+once, so add helpers for fetching current and maximal resource
+limits which do that.
+
+Add them to sched.h (instead of resource.h) due to circular dependency
+ sched.h->resource.h->task_struct
+Alternative would be to create a separate res_access.h or similar.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Cc: James Morris <jmorris@namei.org>
+Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/sched.h | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2232,6 +2232,28 @@ static inline void mm_init_owner(struct
+
+ #define TASK_STATE_TO_CHAR_STR "RSDTtZX"
+
++static inline unsigned long task_rlimit(const struct task_struct *tsk,
++ unsigned int limit)
++{
++ return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_cur);
++}
++
++static inline unsigned long task_rlimit_max(const struct task_struct *tsk,
++ unsigned int limit)
++{
++ return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_max);
++}
++
++static inline unsigned long rlimit(unsigned int limit)
++{
++ return task_rlimit(current, limit);
++}
++
++static inline unsigned long rlimit_max(unsigned int limit)
++{
++ return task_rlimit_max(current, limit);
++}
++
+ #endif /* __KERNEL__ */
+
+ #endif