elf_fdpic_transfer_args_to_stack(): make it generic
authorNicolas Pitre <nicolas.pitre@linaro.org>
Sun, 24 Jul 2016 15:30:18 +0000 (11:30 -0400)
committerGreg Ungerer <gerg@linux-m68k.org>
Mon, 25 Jul 2016 06:51:49 +0000 (16:51 +1000)
This copying of arguments and environment is common to both NOMMU
binary formats we support. Let's make the elf_fdpic version available
to the flat format as well.

While at it, improve the code a bit not to copy below the actual
data area.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Reviewed-by: Greg Ungerer <gerg@linux-m68k.org>
Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
fs/binfmt_elf_fdpic.c
fs/exec.c
include/linux/binfmts.h

index 203589311bf88733bdb53d329a3b05a490ce9164..464a972e88c133a917493bd19a68e375c6dfd1d2 100644 (file)
@@ -67,8 +67,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
                                   struct elf_fdpic_params *);
 
 #ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
-                                           unsigned long *);
 static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
                                                   struct file *,
                                                   struct mm_struct *);
@@ -515,8 +513,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        sp = mm->start_stack;
 
        /* stack the program arguments and environment */
-       if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
+       if (transfer_args_to_stack(bprm, &sp) < 0)
                return -EFAULT;
+       sp &= ~15;
 #endif
 
        /*
@@ -709,39 +708,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        return 0;
 }
 
-/*****************************************************************************/
-/*
- * transfer the program arguments and environment from the holding pages onto
- * the stack
- */
-#ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
-                                           unsigned long *_sp)
-{
-       unsigned long index, stop, sp;
-       char *src;
-       int ret = 0;
-
-       stop = bprm->p >> PAGE_SHIFT;
-       sp = *_sp;
-
-       for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
-               src = kmap(bprm->page[index]);
-               sp -= PAGE_SIZE;
-               if (copy_to_user((void *) sp, src, PAGE_SIZE) != 0)
-                       ret = -EFAULT;
-               kunmap(bprm->page[index]);
-               if (ret < 0)
-                       goto out;
-       }
-
-       *_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
-
-out:
-       return ret;
-}
-#endif
-
 /*****************************************************************************/
 /*
  * load the appropriate binary image (executable or interpreter) into memory
index 887c1c955df8264efc43bd0964f971ac8c107f34..ef0df2f09257677107fdd5eb6e99dd2d4320ac11 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -762,6 +762,39 @@ out_unlock:
 }
 EXPORT_SYMBOL(setup_arg_pages);
 
+#else
+
+/*
+ * Transfer the program arguments and environment from the holding pages
+ * onto the stack. The provided stack pointer is adjusted accordingly.
+ */
+int transfer_args_to_stack(struct linux_binprm *bprm,
+                          unsigned long *sp_location)
+{
+       unsigned long index, stop, sp;
+       int ret = 0;
+
+       stop = bprm->p >> PAGE_SHIFT;
+       sp = *sp_location;
+
+       for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+               unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
+               char *src = kmap(bprm->page[index]) + offset;
+               sp -= PAGE_SIZE - offset;
+               if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
+                       ret = -EFAULT;
+               kunmap(bprm->page[index]);
+               if (ret)
+                       goto out;
+       }
+
+       *sp_location = sp;
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL(transfer_args_to_stack);
+
 #endif /* CONFIG_MMU */
 
 static struct file *do_open_execat(int fd, struct filename *name, int flags)
index 314b3caa701cc20a6c3fcd628de3c48b7c0c7d21..1303b570b18cc98f0c92cc5d08a309c605468cd8 100644 (file)
@@ -113,6 +113,8 @@ extern int suid_dumpable;
 extern int setup_arg_pages(struct linux_binprm * bprm,
                           unsigned long stack_top,
                           int executable_stack);
+extern int transfer_args_to_stack(struct linux_binprm *bprm,
+                                 unsigned long *sp_location);
 extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
                               struct linux_binprm *bprm);