
From: David Howells <dhowells@redhat.com>

The attached patch changes setup_arg_pages() to take the proposed initial stack
top for the new executable image. This makes it easier for the binfmt to place
the stack at a non-fixed location, such as happens in !MMU configurations.

Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/x86_64/ia32/ia32_aout.c   |    5 +++--
 25-akpm/arch/x86_64/ia32/ia32_binfmt.c |    7 ++++---
 25-akpm/fs/binfmt_aout.c               |    2 +-
 25-akpm/fs/binfmt_elf.c                |    2 +-
 25-akpm/fs/binfmt_som.c                |    2 +-
 25-akpm/fs/exec.c                      |   12 +++++++-----
 25-akpm/include/linux/binfmts.h        |    4 +++-
 7 files changed, 20 insertions(+), 14 deletions(-)

diff -puN arch/x86_64/ia32/ia32_aout.c~frv-change-setup_arg_pages-to-take-stack-pointer arch/x86_64/ia32/ia32_aout.c
--- 25/arch/x86_64/ia32/ia32_aout.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.978530488 -0800
+++ 25-akpm/arch/x86_64/ia32/ia32_aout.c	2004-11-30 01:22:54.990528664 -0800
@@ -36,7 +36,8 @@
 #undef WARN_OLD
 #undef CORE_DUMP /* probably broken */
 
-extern int ia32_setup_arg_pages(struct linux_binprm *bprm, int exec_stack);
+extern int ia32_setup_arg_pages(struct linux_binprm *bprm,
+				unsigned long stack_top, int exec_stack);
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
@@ -397,7 +398,7 @@ beyond_if:
 
 	set_brk(current->mm->start_brk, current->mm->brk);
 
-	retval = ia32_setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	retval = ia32_setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
 		send_sig(SIGKILL, current, 0); 
diff -puN arch/x86_64/ia32/ia32_binfmt.c~frv-change-setup_arg_pages-to-take-stack-pointer arch/x86_64/ia32/ia32_binfmt.c
--- 25/arch/x86_64/ia32/ia32_binfmt.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.980530184 -0800
+++ 25-akpm/arch/x86_64/ia32/ia32_binfmt.c	2004-11-30 01:22:54.991528512 -0800
@@ -273,8 +273,9 @@ do {							\
 #define load_elf_binary load_elf32_binary
 
 #define ELF_PLAT_INIT(r, load_addr)	elf32_init(r)
-#define setup_arg_pages(bprm, exec_stack)	ia32_setup_arg_pages(bprm, exec_stack)
-int ia32_setup_arg_pages(struct linux_binprm *bprm, int executable_stack);
+#define setup_arg_pages(bprm, stack_top, exec_stack) \
+	ia32_setup_arg_pages(bprm, stack_top, exec_stack)
+int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack);
 
 #undef start_thread
 #define start_thread(regs,new_rip,new_rsp) do { \
@@ -329,7 +330,7 @@ static void elf32_init(struct pt_regs *r
 	me->thread.es = __USER_DS;
 }
 
-int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
+int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
diff -puN fs/binfmt_aout.c~frv-change-setup_arg_pages-to-take-stack-pointer fs/binfmt_aout.c
--- 25/fs/binfmt_aout.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.981530032 -0800
+++ 25-akpm/fs/binfmt_aout.c	2004-11-30 01:22:54.992528360 -0800
@@ -424,7 +424,7 @@ beyond_if:
 		return retval;
 	}
 
-	retval = setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
 		send_sig(SIGKILL, current, 0); 
diff -puN fs/binfmt_elf.c~frv-change-setup_arg_pages-to-take-stack-pointer fs/binfmt_elf.c
--- 25/fs/binfmt_elf.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.983529728 -0800
+++ 25-akpm/fs/binfmt_elf.c	2004-11-30 01:22:54.993528208 -0800
@@ -736,7 +736,7 @@ static int load_elf_binary(struct linux_
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = current->mm->mmap_base;
-	retval = setup_arg_pages(bprm, executable_stack);
+	retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto out_free_dentry;
diff -puN fs/binfmt_som.c~frv-change-setup_arg_pages-to-take-stack-pointer fs/binfmt_som.c
--- 25/fs/binfmt_som.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.984529576 -0800
+++ 25-akpm/fs/binfmt_som.c	2004-11-30 01:22:54.993528208 -0800
@@ -254,7 +254,7 @@ load_som_binary(struct linux_binprm * bp
 
 	set_binfmt(&som_format);
 	compute_creds(bprm);
-	setup_arg_pages(bprm, EXSTACK_DEFAULT);
+	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 
 	create_som_tables(bprm);
 
diff -puN fs/exec.c~frv-change-setup_arg_pages-to-take-stack-pointer fs/exec.c
--- 25/fs/exec.c~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.986529272 -0800
+++ 25-akpm/fs/exec.c	2004-11-30 01:22:54.995527904 -0800
@@ -342,7 +342,9 @@ out_sig:
 
 #define EXTRA_STACK_VM_PAGES	20	/* random */
 
-int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
+int setup_arg_pages(struct linux_binprm *bprm,
+		    unsigned long stack_top,
+		    int executable_stack)
 {
 	unsigned long stack_base;
 	struct vm_area_struct *mpnt;
@@ -383,7 +385,7 @@ int setup_arg_pages(struct linux_binprm 
 	stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max;
 	if (stack_base > (1 << 30))
 		stack_base = 1 << 30;
-	stack_base = PAGE_ALIGN(STACK_TOP - stack_base);
+	stack_base = PAGE_ALIGN(stack_top - stack_base);
 
 	/* Adjust bprm->p to point to the end of the strings. */
 	bprm->p = stack_base + PAGE_SIZE * i - offset;
@@ -395,10 +397,10 @@ int setup_arg_pages(struct linux_binprm 
 	while (i < MAX_ARG_PAGES)
 		bprm->page[i++] = NULL;
 #else
-	stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+	stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
 	bprm->p += stack_base;
 	mm->arg_start = bprm->p;
-	arg_size = STACK_TOP - (PAGE_MASK & (unsigned long) mm->arg_start);
+	arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
 #endif
 
 	arg_size += EXTRA_STACK_VM_PAGES * PAGE_SIZE;
@@ -425,7 +427,7 @@ int setup_arg_pages(struct linux_binprm 
 		mpnt->vm_start = stack_base;
 		mpnt->vm_end = stack_base + arg_size;
 #else
-		mpnt->vm_end = STACK_TOP;
+		mpnt->vm_end = stack_top;
 		mpnt->vm_start = mpnt->vm_end - arg_size;
 #endif
 		/* Adjust stack execute permissions; explicitly enable
diff -puN include/linux/binfmts.h~frv-change-setup_arg_pages-to-take-stack-pointer include/linux/binfmts.h
--- 25/include/linux/binfmts.h~frv-change-setup_arg_pages-to-take-stack-pointer	2004-11-30 01:22:54.987529120 -0800
+++ 25-akpm/include/linux/binfmts.h	2004-11-30 01:22:54.995527904 -0800
@@ -74,7 +74,9 @@ extern int flush_old_exec(struct linux_b
 #define EXSTACK_DISABLE_X 1	/* Disable executable stacks */
 #define EXSTACK_ENABLE_X  2	/* Enable executable stacks */
 
-extern int setup_arg_pages(struct linux_binprm * bprm, int executable_stack);
+extern int setup_arg_pages(struct linux_binprm * bprm,
+			   unsigned long stack_top,
+			   int executable_stack);
 extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm); 
 extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
 extern void compute_creds(struct linux_binprm *binprm);
_
