Merge branch 'exec-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[sfrench/cifs-2.6.git] / fs / exec.c
index 2f0a74582ac905b7487b985a782cfe662c6c30c1..e850ee7dd636d64fdf342233993fd208b86fcd2b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -72,6 +72,8 @@
 
 #include <trace/events/sched.h>
 
+static int bprm_creds_from_file(struct linux_binprm *bprm);
+
 int suid_dumpable = 0;
 
 static LIST_HEAD(formats);
@@ -1051,13 +1053,14 @@ static int exec_mmap(struct mm_struct *mm)
        tsk = current;
        old_mm = current->mm;
        exec_mm_release(tsk, old_mm);
+       if (old_mm)
+               sync_mm_rss(old_mm);
 
        ret = mutex_lock_killable(&tsk->signal->exec_update_mutex);
        if (ret)
                return ret;
 
        if (old_mm) {
-               sync_mm_rss(old_mm);
                /*
                 * Make sure that if there is a core dump in progress
                 * for the old mm, we get out and die instead of going
@@ -1093,12 +1096,6 @@ static int exec_mmap(struct mm_struct *mm)
        return 0;
 }
 
-/*
- * This function makes sure the current process has its own signal table,
- * so that flush_signal_handlers can later reset the handlers without
- * disturbing other processes.  (Other processes might share the signal
- * table via the CLONE_SIGHAND option to clone().)
- */
 static int de_thread(struct task_struct *tsk)
 {
        struct signal_struct *sig = tsk->signal;
@@ -1236,6 +1233,12 @@ killed:
 }
 
 
+/*
+ * This function makes sure the current process has its own signal table,
+ * so that flush_signal_handlers can later reset the handlers without
+ * disturbing other processes.  (Other processes might share the signal
+ * table via the CLONE_SIGHAND option to clone().)
+ */
 static int unshare_sighand(struct task_struct *me)
 {
        struct sighand_struct *oldsighand = me->sighand;
@@ -1292,13 +1295,23 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
  * Calling this is the point of no return. None of the failures will be
  * seen by userspace since either the process is already taking a fatal
  * signal (via de_thread() or coredump), or will have SEGV raised
- * (after exec_mmap()) by search_binary_handlers (see below).
+ * (after exec_mmap()) by search_binary_handler (see below).
  */
-int flush_old_exec(struct linux_binprm * bprm)
+int begin_new_exec(struct linux_binprm * bprm)
 {
        struct task_struct *me = current;
        int retval;
 
+       /* Once we are committed compute the creds */
+       retval = bprm_creds_from_file(bprm);
+       if (retval)
+               return retval;
+
+       /*
+        * Ensure all future errors are fatal.
+        */
+       bprm->point_of_no_return = true;
+
        /*
         * Make this the only thread in the thread group.
         */
@@ -1313,7 +1326,10 @@ int flush_old_exec(struct linux_binprm * bprm)
         */
        set_mm_exe_file(bprm->mm, bprm->file);
 
+       /* If the binary is not readable then enforce mm->dumpable=0 */
        would_dump(bprm, bprm->file);
+       if (bprm->have_execfd)
+               would_dump(bprm, bprm->executable);
 
        /*
         * Release all of the old mmap stuff
@@ -1323,13 +1339,6 @@ int flush_old_exec(struct linux_binprm * bprm)
        if (retval)
                goto out;
 
-       /*
-        * After setting bprm->called_exec_mmap (to mark that current is
-        * using the prepared mm now), we have nothing left of the original
-        * process. If anything from here on returns an error, the check
-        * in search_binary_handler() will SEGV current.
-        */
-       bprm->called_exec_mmap = 1;
        bprm->mm = NULL;
 
 #ifdef CONFIG_POSIX_TIMERS
@@ -1342,7 +1351,7 @@ int flush_old_exec(struct linux_binprm * bprm)
         */
        retval = unshare_sighand(me);
        if (retval)
-               goto out;
+               goto out_unlock;
 
        set_fs(USER_DS);
        me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
@@ -1357,12 +1366,84 @@ int flush_old_exec(struct linux_binprm * bprm)
         * undergoing exec(2).
         */
        do_close_on_exec(me->files);
+
+       if (bprm->secureexec) {
+               /* Make sure parent cannot signal privileged process. */
+               me->pdeath_signal = 0;
+
+               /*
+                * For secureexec, reset the stack limit to sane default to
+                * avoid bad behavior from the prior rlimits. This has to
+                * happen before arch_pick_mmap_layout(), which examines
+                * RLIMIT_STACK, but after the point of no return to avoid
+                * needing to clean up the change on failure.
+                */
+               if (bprm->rlim_stack.rlim_cur > _STK_LIM)
+                       bprm->rlim_stack.rlim_cur = _STK_LIM;
+       }
+
+       me->sas_ss_sp = me->sas_ss_size = 0;
+
+       /*
+        * Figure out dumpability. Note that this checking only of current
+        * is wrong, but userspace depends on it. This should be testing
+        * bprm->secureexec instead.
+        */
+       if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP ||
+           !(uid_eq(current_euid(), current_uid()) &&
+             gid_eq(current_egid(), current_gid())))
+               set_dumpable(current->mm, suid_dumpable);
+       else
+               set_dumpable(current->mm, SUID_DUMP_USER);
+
+       perf_event_exec();
+       __set_task_comm(me, kbasename(bprm->filename), true);
+
+       /* An exec changes our domain. We are no longer part of the thread
+          group */
+       WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
+       flush_signal_handlers(me, 0);
+
+       /*
+        * install the new credentials for this executable
+        */
+       security_bprm_committing_creds(bprm);
+
+       commit_creds(bprm->cred);
+       bprm->cred = NULL;
+
+       /*
+        * Disable monitoring for regular users
+        * when executing setuid binaries. Must
+        * wait until new credentials are committed
+        * by commit_creds() above
+        */
+       if (get_dumpable(me->mm) != SUID_DUMP_USER)
+               perf_event_exit_task(me);
+       /*
+        * cred_guard_mutex must be held at least to this point to prevent
+        * ptrace_attach() from altering our determination of the task's
+        * credentials; any time after this it may be unlocked.
+        */
+       security_bprm_committed_creds(bprm);
+
+       /* Pass the opened binary to the interpreter. */
+       if (bprm->have_execfd) {
+               retval = get_unused_fd_flags(0);
+               if (retval < 0)
+                       goto out_unlock;
+               fd_install(retval, bprm->executable);
+               bprm->executable = NULL;
+               bprm->execfd = retval;
+       }
        return 0;
 
+out_unlock:
+       mutex_unlock(&me->signal->exec_update_mutex);
 out:
        return retval;
 }
-EXPORT_SYMBOL(flush_old_exec);
+EXPORT_SYMBOL(begin_new_exec);
 
 void would_dump(struct linux_binprm *bprm, struct file *file)
 {
@@ -1387,58 +1468,20 @@ EXPORT_SYMBOL(would_dump);
 
 void setup_new_exec(struct linux_binprm * bprm)
 {
-       /*
-        * Once here, prepare_binrpm() will not be called any more, so
-        * the final state of setuid/setgid/fscaps can be merged into the
-        * secureexec flag.
-        */
-       bprm->secureexec |= bprm->cap_elevated;
-
-       if (bprm->secureexec) {
-               /* Make sure parent cannot signal privileged process. */
-               current->pdeath_signal = 0;
-
-               /*
-                * For secureexec, reset the stack limit to sane default to
-                * avoid bad behavior from the prior rlimits. This has to
-                * happen before arch_pick_mmap_layout(), which examines
-                * RLIMIT_STACK, but after the point of no return to avoid
-                * needing to clean up the change on failure.
-                */
-               if (bprm->rlim_stack.rlim_cur > _STK_LIM)
-                       bprm->rlim_stack.rlim_cur = _STK_LIM;
-       }
-
-       arch_pick_mmap_layout(current->mm, &bprm->rlim_stack);
-
-       current->sas_ss_sp = current->sas_ss_size = 0;
+       /* Setup things that can depend upon the personality */
+       struct task_struct *me = current;
 
-       /*
-        * Figure out dumpability. Note that this checking only of current
-        * is wrong, but userspace depends on it. This should be testing
-        * bprm->secureexec instead.
-        */
-       if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP ||
-           !(uid_eq(current_euid(), current_uid()) &&
-             gid_eq(current_egid(), current_gid())))
-               set_dumpable(current->mm, suid_dumpable);
-       else
-               set_dumpable(current->mm, SUID_DUMP_USER);
+       arch_pick_mmap_layout(me->mm, &bprm->rlim_stack);
 
        arch_setup_new_exec();
-       perf_event_exec();
-       __set_task_comm(current, kbasename(bprm->filename), true);
 
        /* Set the new mm task size. We have to do that late because it may
         * depend on TIF_32BIT which is only updated in flush_thread() on
         * some architectures like powerpc
         */
-       current->mm->task_size = TASK_SIZE;
-
-       /* An exec changes our domain. We are no longer part of the thread
-          group */
-       WRITE_ONCE(current->self_exec_id, current->self_exec_id + 1);
-       flush_signal_handlers(current, 0);
+       me->mm->task_size = TASK_SIZE;
+       mutex_unlock(&me->signal->exec_update_mutex);
+       mutex_unlock(&me->signal->cred_guard_mutex);
 }
 EXPORT_SYMBOL(setup_new_exec);
 
@@ -1454,7 +1497,7 @@ EXPORT_SYMBOL(finalize_exec);
 
 /*
  * Prepare credentials and lock ->cred_guard_mutex.
- * install_exec_creds() commits the new creds and drops the lock.
+ * setup_new_exec() commits the new creds and drops the lock.
  * Or, if exec fails before, free_bprm() should release ->cred and
  * and unlock.
  */
@@ -1475,8 +1518,6 @@ static void free_bprm(struct linux_binprm *bprm)
 {
        free_arg_pages(bprm);
        if (bprm->cred) {
-               if (bprm->called_exec_mmap)
-                       mutex_unlock(&current->signal->exec_update_mutex);
                mutex_unlock(&current->signal->cred_guard_mutex);
                abort_creds(bprm->cred);
        }
@@ -1484,6 +1525,8 @@ static void free_bprm(struct linux_binprm *bprm)
                allow_write_access(bprm->file);
                fput(bprm->file);
        }
+       if (bprm->executable)
+               fput(bprm->executable);
        /* If a binfmt changed the interp, free it. */
        if (bprm->interp != bprm->filename)
                kfree(bprm->interp);
@@ -1502,35 +1545,6 @@ int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
 }
 EXPORT_SYMBOL(bprm_change_interp);
 
-/*
- * install the new credentials for this executable
- */
-void install_exec_creds(struct linux_binprm *bprm)
-{
-       security_bprm_committing_creds(bprm);
-
-       commit_creds(bprm->cred);
-       bprm->cred = NULL;
-
-       /*
-        * Disable monitoring for regular users
-        * when executing setuid binaries. Must
-        * wait until new credentials are committed
-        * by commit_creds() above
-        */
-       if (get_dumpable(current->mm) != SUID_DUMP_USER)
-               perf_event_exit_task(current);
-       /*
-        * cred_guard_mutex must be held at least to this point to prevent
-        * ptrace_attach() from altering our determination of the task's
-        * credentials; any time after this it may be unlocked.
-        */
-       security_bprm_committed_creds(bprm);
-       mutex_unlock(&current->signal->exec_update_mutex);
-       mutex_unlock(&current->signal->cred_guard_mutex);
-}
-EXPORT_SYMBOL(install_exec_creds);
-
 /*
  * determine how safe it is to execute the proposed program
  * - the caller must hold ->cred_guard_mutex to protect against
@@ -1568,29 +1582,21 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
        spin_unlock(&p->fs->lock);
 }
 
-static void bprm_fill_uid(struct linux_binprm *bprm)
+static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
 {
+       /* Handle suid and sgid on files */
        struct inode *inode;
        unsigned int mode;
        kuid_t uid;
        kgid_t gid;
 
-       /*
-        * Since this can be called multiple times (via prepare_binprm),
-        * we must clear any previous work done when setting set[ug]id
-        * bits from any earlier bprm->file uses (for example when run
-        * first for a setuid script then again for its interpreter).
-        */
-       bprm->cred->euid = current_euid();
-       bprm->cred->egid = current_egid();
-
-       if (!mnt_may_suid(bprm->file->f_path.mnt))
+       if (!mnt_may_suid(file->f_path.mnt))
                return;
 
        if (task_no_new_privs(current))
                return;
 
-       inode = bprm->file->f_path.dentry->d_inode;
+       inode = file->f_path.dentry->d_inode;
        mode = READ_ONCE(inode->i_mode);
        if (!(mode & (S_ISUID|S_ISGID)))
                return;
@@ -1620,31 +1626,32 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
        }
 }
 
+/*
+ * Compute brpm->cred based upon the final binary.
+ */
+static int bprm_creds_from_file(struct linux_binprm *bprm)
+{
+       /* Compute creds based on which file? */
+       struct file *file = bprm->execfd_creds ? bprm->executable : bprm->file;
+
+       bprm_fill_uid(bprm, file);
+       return security_bprm_creds_from_file(bprm, file);
+}
+
 /*
  * Fill the binprm structure from the inode.
- * Check permissions, then read the first BINPRM_BUF_SIZE bytes
+ * Read the first BINPRM_BUF_SIZE bytes
  *
  * This may be called multiple times for binary chains (scripts for example).
  */
-int prepare_binprm(struct linux_binprm *bprm)
+static int prepare_binprm(struct linux_binprm *bprm)
 {
-       int retval;
        loff_t pos = 0;
 
-       bprm_fill_uid(bprm);
-
-       /* fill in binprm security blob */
-       retval = security_bprm_set_creds(bprm);
-       if (retval)
-               return retval;
-       bprm->called_set_creds = 1;
-
        memset(bprm->buf, 0, BINPRM_BUF_SIZE);
        return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
 }
 
-EXPORT_SYMBOL(prepare_binprm);
-
 /*
  * Arguments are '\0' separated strings found at the location bprm->p
  * points to; chop off the first by relocating brpm->p to right after
@@ -1690,15 +1697,15 @@ EXPORT_SYMBOL(remove_arg_zero);
 /*
  * cycle the list of binary formats handler, until one recognizes the image
  */
-int search_binary_handler(struct linux_binprm *bprm)
+static int search_binary_handler(struct linux_binprm *bprm)
 {
        bool need_retry = IS_ENABLED(CONFIG_MODULES);
        struct linux_binfmt *fmt;
        int retval;
 
-       /* This allows 4 levels of binfmt rewrites before failing hard. */
-       if (bprm->recursion_depth > 5)
-               return -ELOOP;
+       retval = prepare_binprm(bprm);
+       if (retval < 0)
+               return retval;
 
        retval = security_bprm_check(bprm);
        if (retval)
@@ -1712,19 +1719,11 @@ int search_binary_handler(struct linux_binprm *bprm)
                        continue;
                read_unlock(&binfmt_lock);
 
-               bprm->recursion_depth++;
                retval = fmt->load_binary(bprm);
-               bprm->recursion_depth--;
 
                read_lock(&binfmt_lock);
                put_binfmt(fmt);
-               if (retval < 0 && bprm->called_exec_mmap) {
-                       /* we got to flush_old_exec() and failed after it */
-                       read_unlock(&binfmt_lock);
-                       force_sigsegv(SIGSEGV);
-                       return retval;
-               }
-               if (retval != -ENOEXEC || !bprm->file) {
+               if (bprm->point_of_no_return || (retval != -ENOEXEC)) {
                        read_unlock(&binfmt_lock);
                        return retval;
                }
@@ -1743,12 +1742,11 @@ int search_binary_handler(struct linux_binprm *bprm)
 
        return retval;
 }
-EXPORT_SYMBOL(search_binary_handler);
 
 static int exec_binprm(struct linux_binprm *bprm)
 {
        pid_t old_pid, old_vpid;
-       int ret;
+       int ret, depth;
 
        /* Need to fetch pid before load_binary changes it */
        old_pid = current->pid;
@@ -1756,15 +1754,38 @@ static int exec_binprm(struct linux_binprm *bprm)
        old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
        rcu_read_unlock();
 
-       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);
-               proc_exec_connector(current);
+       /* This allows 4 levels of binfmt rewrites before failing hard. */
+       for (depth = 0;; depth++) {
+               struct file *exec;
+               if (depth > 5)
+                       return -ELOOP;
+
+               ret = search_binary_handler(bprm);
+               if (ret < 0)
+                       return ret;
+               if (!bprm->interpreter)
+                       break;
+
+               exec = bprm->file;
+               bprm->file = bprm->interpreter;
+               bprm->interpreter = NULL;
+
+               allow_write_access(exec);
+               if (unlikely(bprm->have_execfd)) {
+                       if (bprm->executable) {
+                               fput(exec);
+                               return -ENOEXEC;
+                       }
+                       bprm->executable = exec;
+               } else
+                       fput(exec);
        }
 
-       return ret;
+       audit_bprm(bprm);
+       trace_sched_process_exec(current, old_pid, bprm);
+       ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
+       proc_exec_connector(current);
+       return 0;
 }
 
 /*
@@ -1857,8 +1878,9 @@ static int __do_execve_file(int fd, struct filename *filename,
        if (retval < 0)
                goto out;
 
-       retval = prepare_binprm(bprm);
-       if (retval < 0)
+       /* Set the unchanging part of bprm->cred */
+       retval = security_bprm_creds_for_exec(bprm);
+       if (retval)
                goto out;
 
        retval = copy_strings_kernel(1, &bprm->filename, bprm);
@@ -1893,6 +1915,14 @@ static int __do_execve_file(int fd, struct filename *filename,
        return retval;
 
 out:
+       /*
+        * If past the point of no return ensure the the code never
+        * returns to the userspace process.  Use an existing fatal
+        * signal if present otherwise terminate the process with
+        * SIGSEGV.
+        */
+       if (bprm->point_of_no_return && !fatal_signal_pending(current))
+               force_sigsegv(SIGSEGV);
        if (bprm->mm) {
                acct_arg_size(bprm, 0);
                mmput(bprm->mm);