]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/exec.c
mm: correctly synchronize rss-counters at exit/exec
[karo-tx-linux.git] / fs / exec.c
index b1fd2025e59a1e0ea0a2f475b812987dac176e9f..b926ed19301e270c6717b3156118b5fcee87c22c 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -280,10 +280,6 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        INIT_LIST_HEAD(&vma->anon_vma_chain);
 
-       err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
-       if (err)
-               goto err;
-
        err = insert_vm_struct(mm, vma);
        if (err)
                goto err;
@@ -823,7 +819,6 @@ static int exec_mmap(struct mm_struct *mm)
        /* Notify parent that we're no longer interested in the old VM */
        tsk = current;
        old_mm = current->mm;
-       sync_mm_rss(old_mm);
        mm_release(tsk, old_mm);
 
        if (old_mm) {
@@ -1139,7 +1134,7 @@ void setup_new_exec(struct linux_binprm * bprm)
        /* This is the point of no return */
        current->sas_ss_sp = current->sas_ss_size = 0;
 
-       if (current_euid() == current_uid() && current_egid() == current_gid())
+       if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid()))
                set_dumpable(current->mm, 1);
        else
                set_dumpable(current->mm, suid_dumpable);
@@ -1153,8 +1148,8 @@ void setup_new_exec(struct linux_binprm * bprm)
        current->mm->task_size = TASK_SIZE;
 
        /* install the new credentials */
-       if (bprm->cred->uid != current_euid() ||
-           bprm->cred->gid != current_egid()) {
+       if (!uid_eq(bprm->cred->uid, current_euid()) ||
+           !gid_eq(bprm->cred->gid, current_egid())) {
                current->pdeath_signal = 0;
        } else {
                would_dump(bprm, bprm->file);
@@ -1245,6 +1240,13 @@ static int check_unsafe_exec(struct linux_binprm *bprm)
                        bprm->unsafe |= LSM_UNSAFE_PTRACE;
        }
 
+       /*
+        * This isn't strictly necessary, but it makes it harder for LSMs to
+        * mess up.
+        */
+       if (current->no_new_privs)
+               bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
+
        n_fs = 1;
        spin_lock(&p->fs->lock);
        rcu_read_lock();
@@ -1288,11 +1290,15 @@ int prepare_binprm(struct linux_binprm *bprm)
        bprm->cred->euid = current_euid();
        bprm->cred->egid = current_egid();
 
-       if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+       if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
+           !current->no_new_privs) {
                /* Set-uid? */
                if (mode & S_ISUID) {
+                       if (!kuid_has_mapping(bprm->cred->user_ns, inode->i_uid))
+                               return -EPERM;
                        bprm->per_clear |= PER_CLEAR_ON_SETID;
                        bprm->cred->euid = inode->i_uid;
+
                }
 
                /* Set-gid? */
@@ -1302,6 +1308,8 @@ int prepare_binprm(struct linux_binprm *bprm)
                 * executable.
                 */
                if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+                       if (!kgid_has_mapping(bprm->cred->user_ns, inode->i_gid))
+                               return -EPERM;
                        bprm->per_clear |= PER_CLEAR_ON_SETID;
                        bprm->cred->egid = inode->i_gid;
                }
@@ -1930,8 +1938,21 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
                core_waiters = zap_threads(tsk, mm, core_state, exit_code);
        up_write(&mm->mmap_sem);
 
-       if (core_waiters > 0)
+       if (core_waiters > 0) {
+               struct core_thread *ptr;
+
                wait_for_completion(&core_state->startup);
+               /*
+                * Wait for all the threads to become inactive, so that
+                * all the thread context (extended register state, like
+                * fpu etc) gets copied to the memory.
+                */
+               ptr = core_state->dumper.next;
+               while (ptr != NULL) {
+                       wait_task_inactive(ptr->task, 0);
+                       ptr = ptr->next;
+               }
+       }
 
        return core_waiters;
 }
@@ -2121,7 +2142,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        if (__get_dumpable(cprm.mm_flags) == 2) {
                /* Setuid core dump mode */
                flag = O_EXCL;          /* Stop rewrite attacks */
-               cred->fsuid = 0;        /* Dump root private */
+               cred->fsuid = GLOBAL_ROOT_UID;  /* Dump root private */
        }
 
        retval = coredump_wait(exit_code, &core_state);
@@ -2222,7 +2243,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
                 * Dont allow local users get cute and trick others to coredump
                 * into their pre-created files.
                 */
-               if (inode->i_uid != current_fsuid())
+               if (!uid_eq(inode->i_uid, current_fsuid()))
                        goto close_fail;
                if (!cprm.file->f_op || !cprm.file->f_op->write)
                        goto close_fail;