exec: cleanup the error handling in search_binary_handler()
authorOleg Nesterov <oleg@redhat.com>
Wed, 11 Sep 2013 21:24:46 +0000 (14:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Sep 2013 22:59:09 +0000 (15:59 -0700)
The error hanling and ret-from-loop look confusing and inconsistent.

- "retval >= 0" simply returns

- "!bprm->file" returns too but with read_unlock() because
   binfmt_lock was already re-acquired

- "retval != -ENOEXEC || bprm->mm == NULL" does "break" and
  relies on the same check after the main loop

Consolidate these checks into a single if/return statement.

need_retry still checks "retval == -ENOEXEC", but this and -ENOENT before
the main loop are not needed.  This is only for pathological and
impossible list_empty(&formats) case.

It is not clear why do we check "bprm->mm == NULL", probably this
should be removed.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Zach Levis <zml@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/exec.c

index 635b586de336e84a90ca33130566efe6079d6aa5..8875dd10ae7ac77444db95e33c9fde83dde67512 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1399,22 +1399,17 @@ int search_binary_handler(struct linux_binprm *bprm)
                bprm->recursion_depth++;
                retval = fmt->load_binary(bprm);
                bprm->recursion_depth--;
-               if (retval >= 0) {
+               if (retval >= 0 || retval != -ENOEXEC ||
+                   bprm->mm == NULL || bprm->file == NULL) {
                        put_binfmt(fmt);
                        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;
-               }
        }
        read_unlock(&binfmt_lock);
 
-       if (need_retry && retval == -ENOEXEC && bprm->mm) {
+       if (need_retry && retval == -ENOEXEC) {
                if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
                    printable(bprm->buf[2]) && printable(bprm->buf[3]))
                        return retval;