[PATCH] x86: i8253/i8259A lock cleanup
[pandora-kernel.git] / fs / exec.c
index 3a4b35a..4887191 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -58,6 +58,9 @@
 
 int core_uses_pid;
 char core_pattern[65] = "core";
+int suid_dumpable = 0;
+
+EXPORT_SYMBOL(suid_dumpable);
 /* The maximal length of core_pattern is also specified in sysctl.c */
 
 static struct linux_binfmt *formats;
@@ -864,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm)
 
        if (current->euid == current->uid && current->egid == current->gid)
                current->mm->dumpable = 1;
+       else
+               current->mm->dumpable = suid_dumpable;
+
        name = bprm->filename;
 
        /* Copies the binary name from after last slash */
@@ -884,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm)
            permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
            (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
                suid_keys(current);
-               current->mm->dumpable = 0;
+               current->mm->dumpable = suid_dumpable;
        }
 
        /* An exec changes our domain. We are no longer part of the thread
@@ -1432,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        struct inode * inode;
        struct file * file;
        int retval = 0;
+       int fsuid = current->fsuid;
+       int flag = 0;
 
        binfmt = current->binfmt;
        if (!binfmt || !binfmt->core_dump)
@@ -1441,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                up_write(&mm->mmap_sem);
                goto fail;
        }
+
+       /*
+        *      We cannot trust fsuid as being the "true" uid of the
+        *      process nor do we know its entire history. We only know it
+        *      was tainted so we dump it as root in mode 2.
+        */
+       if (mm->dumpable == 2) {        /* Setuid core dump mode */
+               flag = O_EXCL;          /* Stop rewrite attacks */
+               current->fsuid = 0;     /* Dump root private */
+       }
        mm->dumpable = 0;
        init_completion(&mm->core_done);
        spin_lock_irq(&current->sighand->siglock);
@@ -1466,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        lock_kernel();
        format_corename(corename, core_pattern, signr);
        unlock_kernel();
-       file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
+       file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
        if (IS_ERR(file))
                goto fail_unlock;
        inode = file->f_dentry->d_inode;
@@ -1491,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 close_fail:
        filp_close(file, NULL);
 fail_unlock:
+       current->fsuid = fsuid;
        complete_all(&mm->core_done);
 fail:
        return retval;