aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
authorOllie Wild <aaw@google.com>2007-07-19 04:48:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:45 -0400
commitb6a2fea39318e43fee84fa7b0b90d68bed92d2ba (patch)
treec9c3619cb2730b5c10c7427b837146bce3d69156 /fs/binfmt_elf.c
parentbdf4c48af20a3b0f01671799ace345e3d49576da (diff)
mm: variable length argument support
Remove the arg+env limit of MAX_ARG_PAGES by copying the strings directly from the old mm into the new mm. We create the new mm before the binfmt code runs, and place the new stack at the very top of the address space. Once the binfmt code runs and figures out where the stack should be, we move it downwards. It is a bit peculiar in that we have one task with two mm's, one of which is inactive. [a.p.zijlstra@chello.nl: limit stack size] Signed-off-by: Ollie Wild <aaw@google.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: <linux-arch@vger.kernel.org> Cc: Hugh Dickins <hugh@veritas.com> [bunk@stusta.de: unexport bprm_mm_init] Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index a27e42bf3400..295cbaa0e58a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -148,6 +148,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
148 elf_addr_t *elf_info; 148 elf_addr_t *elf_info;
149 int ei_index = 0; 149 int ei_index = 0;
150 struct task_struct *tsk = current; 150 struct task_struct *tsk = current;
151 struct vm_area_struct *vma;
151 152
152 /* 153 /*
153 * If this architecture has a platform capability string, copy it 154 * If this architecture has a platform capability string, copy it
@@ -234,6 +235,15 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
234 sp = (elf_addr_t __user *)bprm->p; 235 sp = (elf_addr_t __user *)bprm->p;
235#endif 236#endif
236 237
238
239 /*
240 * Grow the stack manually; some architectures have a limit on how
241 * far ahead a user-space access may be in order to grow the stack.
242 */
243 vma = find_extend_vma(current->mm, bprm->p);
244 if (!vma)
245 return -EFAULT;
246
237 /* Now, let's put argc (and argv, envp if appropriate) on the stack */ 247 /* Now, let's put argc (and argv, envp if appropriate) on the stack */
238 if (__put_user(argc, sp++)) 248 if (__put_user(argc, sp++))
239 return -EFAULT; 249 return -EFAULT;
@@ -254,8 +264,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
254 size_t len; 264 size_t len;
255 if (__put_user((elf_addr_t)p, argv++)) 265 if (__put_user((elf_addr_t)p, argv++))
256 return -EFAULT; 266 return -EFAULT;
257 len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES); 267 len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
258 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES) 268 if (!len || len > MAX_ARG_STRLEN)
259 return 0; 269 return 0;
260 p += len; 270 p += len;
261 } 271 }
@@ -266,8 +276,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
266 size_t len; 276 size_t len;
267 if (__put_user((elf_addr_t)p, envp++)) 277 if (__put_user((elf_addr_t)p, envp++))
268 return -EFAULT; 278 return -EFAULT;
269 len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES); 279 len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
270 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES) 280 if (!len || len > MAX_ARG_STRLEN)
271 return 0; 281 return 0;
272 p += len; 282 p += len;
273 } 283 }
@@ -826,10 +836,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
826 } 836 }
827 837
828 /* OK, This is the point of no return */ 838 /* OK, This is the point of no return */
829 current->mm->start_data = 0;
830 current->mm->end_data = 0;
831 current->mm->end_code = 0;
832 current->mm->mmap = NULL;
833 current->flags &= ~PF_FORKNOEXEC; 839 current->flags &= ~PF_FORKNOEXEC;
834 current->mm->def_flags = def_flags; 840 current->mm->def_flags = def_flags;
835 841
@@ -1051,9 +1057,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1051 1057
1052 compute_creds(bprm); 1058 compute_creds(bprm);
1053 current->flags &= ~PF_FORKNOEXEC; 1059 current->flags &= ~PF_FORKNOEXEC;
1054 create_elf_tables(bprm, &loc->elf_ex, 1060 retval = create_elf_tables(bprm, &loc->elf_ex,
1055 (interpreter_type == INTERPRETER_AOUT), 1061 (interpreter_type == INTERPRETER_AOUT),
1056 load_addr, interp_load_addr); 1062 load_addr, interp_load_addr);
1063 if (retval < 0) {
1064 send_sig(SIGKILL, current, 0);
1065 goto out;
1066 }
1057 /* N.B. passed_fileno might not be initialized? */ 1067 /* N.B. passed_fileno might not be initialized? */
1058 if (interpreter_type == INTERPRETER_AOUT) 1068 if (interpreter_type == INTERPRETER_AOUT)
1059 current->mm->arg_start += strlen(passed_fileno) + 1; 1069 current->mm->arg_start += strlen(passed_fileno) + 1;