Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[safe/jmp/linux-2.6] / kernel / ptrace.c
index 8dcb8f6..019e04e 100644 (file)
@@ -118,6 +118,33 @@ int ptrace_check_attach(struct task_struct *child, int kill)
        return ret;
 }
 
+static int may_attach(struct task_struct *task)
+{
+       if (!task->mm)
+               return -EPERM;
+       if (((current->uid != task->euid) ||
+            (current->uid != task->suid) ||
+            (current->uid != task->uid) ||
+            (current->gid != task->egid) ||
+            (current->gid != task->sgid) ||
+            (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+       smp_rmb();
+       if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+
+       return security_ptrace(current, task);
+}
+
+int ptrace_may_attach(struct task_struct *task)
+{
+       int err;
+       task_lock(task);
+       err = may_attach(task);
+       task_unlock(task);
+       return !err;
+}
+
 int ptrace_attach(struct task_struct *task)
 {
        int retval;
@@ -127,22 +154,10 @@ int ptrace_attach(struct task_struct *task)
                goto bad;
        if (task == current)
                goto bad;
-       if (!task->mm)
-               goto bad;
-       if(((current->uid != task->euid) ||
-           (current->uid != task->suid) ||
-           (current->uid != task->uid) ||
-           (current->gid != task->egid) ||
-           (current->gid != task->sgid) ||
-           (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-               goto bad;
-       smp_rmb();
-       if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
-               goto bad;
        /* the same process cannot be attached many times */
        if (task->ptrace & PT_PTRACED)
                goto bad;
-       retval = security_ptrace(current, task);
+       retval = may_attach(task);
        if (retval)
                goto bad;