Merge tag 'v3.12'
authorEric Paris <eparis@redhat.com>
Fri, 22 Nov 2013 23:57:08 +0000 (18:57 -0500)
committerEric Paris <eparis@redhat.com>
Fri, 22 Nov 2013 23:57:54 +0000 (18:57 -0500)
Linux 3.12

Conflicts:
fs/exec.c

1  2 
fs/exec.c
fs/namei.c
init/Kconfig
kernel/audit.c

diff --cc fs/exec.c
+++ b/fs/exec.c
@@@ -1383,72 -1385,71 +1385,68 @@@ int search_binary_handler(struct linux_
        if (retval)
                return retval;
  
 -      retval = audit_bprm(bprm);
 -      if (retval)
 -              return retval;
 -
+       retval = -ENOENT;
+  retry:
+       read_lock(&binfmt_lock);
+       list_for_each_entry(fmt, &formats, lh) {
+               if (!try_module_get(fmt->module))
+                       continue;
+               read_unlock(&binfmt_lock);
+               bprm->recursion_depth++;
+               retval = fmt->load_binary(bprm);
+               bprm->recursion_depth--;
+               if (retval >= 0 || retval != -ENOEXEC ||
+                   bprm->mm == NULL || bprm->file == NULL) {
+                       put_binfmt(fmt);
+                       return retval;
+               }
+               read_lock(&binfmt_lock);
+               put_binfmt(fmt);
+       }
+       read_unlock(&binfmt_lock);
+       if (need_retry && retval == -ENOEXEC) {
+               if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
+                   printable(bprm->buf[2]) && printable(bprm->buf[3]))
+                       return retval;
+               if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0)
+                       return retval;
+               need_retry = false;
+               goto retry;
+       }
+       return retval;
+ }
+ EXPORT_SYMBOL(search_binary_handler);
+ static int exec_binprm(struct linux_binprm *bprm)
+ {
+       pid_t old_pid, old_vpid;
+       int ret;
        /* Need to fetch pid before load_binary changes it */
        old_pid = current->pid;
        rcu_read_lock();
        old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
        rcu_read_unlock();
  
-       retval = -ENOENT;
-       for (try=0; try<2; try++) {
-               read_lock(&binfmt_lock);
-               list_for_each_entry(fmt, &formats, lh) {
-                       int (*fn)(struct linux_binprm *) = fmt->load_binary;
-                       if (!fn)
-                               continue;
-                       if (!try_module_get(fmt->module))
-                               continue;
-                       read_unlock(&binfmt_lock);
-                       bprm->recursion_depth = depth + 1;
-                       retval = fn(bprm);
-                       bprm->recursion_depth = depth;
-                       if (retval >= 0) {
-                               if (depth == 0) {
-                                       audit_bprm(bprm);
-                                       trace_sched_process_exec(current, old_pid, bprm);
-                                       ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
-                               }
-                               put_binfmt(fmt);
-                               allow_write_access(bprm->file);
-                               if (bprm->file)
-                                       fput(bprm->file);
-                               bprm->file = NULL;
-                               current->did_exec = 1;
-                               proc_exec_connector(current);
-                               return retval;
-                       }
-                       read_lock(&binfmt_lock);
-                       put_binfmt(fmt);
-                       if (retval != -ENOEXEC || bprm->mm == NULL)
-                               break;
-                       if (!bprm->file) {
-                               read_unlock(&binfmt_lock);
-                               return retval;
-                       }
+       ret = search_binary_handler(bprm);
+       if (ret >= 0) {
++              audit_bprm(bprm);
+               trace_sched_process_exec(current, old_pid, bprm);
+               ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
+               current->did_exec = 1;
+               proc_exec_connector(current);
+               if (bprm->file) {
+                       allow_write_access(bprm->file);
+                       fput(bprm->file);
+                       bprm->file = NULL; /* to catch use-after-free */
                }
-               read_unlock(&binfmt_lock);
- #ifdef CONFIG_MODULES
-               if (retval != -ENOEXEC || bprm->mm == NULL) {
-                       break;
-               } else {
- #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
-                       if (printable(bprm->buf[0]) &&
-                           printable(bprm->buf[1]) &&
-                           printable(bprm->buf[2]) &&
-                           printable(bprm->buf[3]))
-                               break; /* -ENOEXEC */
-                       if (try)
-                               break; /* -ENOEXEC */
-                       request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
-               }
- #else
-               break;
- #endif
        }
-       return retval;
- }
  
- EXPORT_SYMBOL(search_binary_handler);
+       return ret;
+ }
  
  /*
   * sys_execve() executes a new program.
diff --cc fs/namei.c
Simple merge
diff --cc init/Kconfig
Simple merge
diff --cc kernel/audit.c
Simple merge