]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/exec.c
tracehook: exec
[linux-2.6-omap-h63xx.git] / fs / exec.c
index c74bb34eeeff032f1d45809bc2a736e15bbab8e2..b8792a13153377f83bc465a320eb35d6d0bd2c33 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #include <linux/module.h>
 #include <linux/namei.h>
 #include <linux/proc_fs.h>
-#include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1071,13 +1071,8 @@ EXPORT_SYMBOL(prepare_binprm);
 
 static int unsafe_exec(struct task_struct *p)
 {
-       int unsafe = 0;
-       if (p->ptrace & PT_PTRACED) {
-               if (p->ptrace & PT_PTRACE_CAP)
-                       unsafe |= LSM_UNSAFE_PTRACE_CAP;
-               else
-                       unsafe |= LSM_UNSAFE_PTRACE;
-       }
+       int unsafe = tracehook_unsafe_exec(p);
+
        if (atomic_read(&p->fs->count) > 1 ||
            atomic_read(&p->files->count) > 1 ||
            atomic_read(&p->sighand->count) > 1)
@@ -1214,6 +1209,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        read_unlock(&binfmt_lock);
                        retval = fn(bprm, regs);
                        if (retval >= 0) {
+                               tracehook_report_exec(fmt, bprm, regs);
                                put_binfmt(fmt);
                                allow_write_access(bprm->file);
                                if (bprm->file)
@@ -1379,17 +1375,14 @@ EXPORT_SYMBOL(set_binfmt);
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-static int format_corename(char *corename, const char *pattern, long signr)
+static int format_corename(char *corename, int nr_threads, long signr)
 {
-       const char *pat_ptr = pattern;
+       const char *pat_ptr = core_pattern;
+       int ispipe = (*pat_ptr == '|');
        char *out_ptr = corename;
        char *const out_end = corename + CORENAME_MAX_SIZE;
        int rc;
        int pid_in_pattern = 0;
-       int ispipe = 0;
-
-       if (*pattern == '|')
-               ispipe = 1;
 
        /* Repeat as long as we have more pattern to process and more output
           space */
@@ -1490,7 +1483,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
         * and core_uses_pid is set, then .%pid will be appended to
         * the filename. Do not do this for piped commands. */
        if (!ispipe && !pid_in_pattern
-            && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
+           && (core_uses_pid || nr_threads)) {
                rc = snprintf(out_ptr, out_end - out_ptr,
                              ".%d", task_tgid_vnr(current));
                if (rc > out_end - out_ptr)
@@ -1591,21 +1584,21 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
        }
        rcu_read_unlock();
 done:
-       core_state->nr_threads = nr;
+       atomic_set(&core_state->nr_threads, nr);
        return nr;
 }
 
-static int coredump_wait(int exit_code)
+static int coredump_wait(int exit_code, struct core_state *core_state)
 {
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       struct core_state core_state;
        struct completion *vfork_done;
        int core_waiters;
 
-       init_completion(&mm->core_done);
-       init_completion(&core_state.startup);
-       core_waiters = zap_threads(tsk, mm, &core_state, exit_code);
+       init_completion(&core_state->startup);
+       core_state->dumper.task = tsk;
+       core_state->dumper.next = NULL;
+       core_waiters = zap_threads(tsk, mm, core_state, exit_code);
        up_write(&mm->mmap_sem);
 
        if (unlikely(core_waiters < 0))
@@ -1622,12 +1615,32 @@ static int coredump_wait(int exit_code)
        }
 
        if (core_waiters)
-               wait_for_completion(&core_state.startup);
-       mm->core_state = NULL;
+               wait_for_completion(&core_state->startup);
 fail:
        return core_waiters;
 }
 
+static void coredump_finish(struct mm_struct *mm)
+{
+       struct core_thread *curr, *next;
+       struct task_struct *task;
+
+       next = mm->core_state->dumper.next;
+       while ((curr = next) != NULL) {
+               next = curr->next;
+               task = curr->task;
+               /*
+                * see exit_mm(), curr->task must not see
+                * ->task == NULL before we read ->next.
+                */
+               smp_mb();
+               curr->task = NULL;
+               wake_up_process(task);
+       }
+
+       mm->core_state = NULL;
+}
+
 /*
  * set_dumpable converts traditional three-value dumpable to two flags and
  * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
@@ -1679,6 +1692,7 @@ int get_dumpable(struct mm_struct *mm)
 
 int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 {
+       struct core_state core_state;
        char corename[CORENAME_MAX_SIZE + 1];
        struct mm_struct *mm = current->mm;
        struct linux_binfmt * binfmt;
@@ -1717,7 +1731,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                current->fsuid = 0;     /* Dump root private */
        }
 
-       retval = coredump_wait(exit_code);
+       retval = coredump_wait(exit_code, &core_state);
        if (retval < 0)
                goto fail;
 
@@ -1732,7 +1746,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
         * uses lock_kernel()
         */
        lock_kernel();
-       ispipe = format_corename(corename, core_pattern, signr);
+       ispipe = format_corename(corename, retval, signr);
        unlock_kernel();
        /*
         * Don't bother to check the RLIMIT_CORE value if core_pattern points
@@ -1811,7 +1825,7 @@ fail_unlock:
                argv_free(helper_argv);
 
        current->fsuid = fsuid;
-       complete_all(&mm->core_done);
+       coredump_finish(mm);
 fail:
        return retval;
 }