]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/ptrace.c
ptrace: ptrace_attach: check PF_KTHREAD + exit_state instead of ->mm
[karo-tx-linux.git] / kernel / ptrace.c
index 0692ab5a0d672341000d1697d7c308c566060fb4..9439bd3331a66a5c541fe5c8ae02c6a70c482290 100644 (file)
 #include <linux/uaccess.h>
 
 
-/*
- * Initialize a new task whose father had been ptraced.
- *
- * Called from copy_process().
- */
-void ptrace_fork(struct task_struct *child, unsigned long clone_flags)
-{
-       arch_ptrace_fork(child, clone_flags);
-}
-
 /*
  * ptrace a task: make the debugger its new parent and
  * move it to the ptrace list.
@@ -182,17 +172,18 @@ int ptrace_attach(struct task_struct *task)
        audit_ptrace(task);
 
        retval = -EPERM;
+       if (unlikely(task->flags & PF_KTHREAD))
+               goto out;
        if (same_thread_group(task, current))
                goto out;
 
-       /* Protect exec's credential calculations against our interference;
-        * SUID, SGID and LSM creds get determined differently under ptrace.
+       /* Protect the target's credential calculations against our
+        * interference; SUID, SGID and LSM creds get determined differently
+        * under ptrace.
         */
-       retval = mutex_lock_interruptible(&task->cred_exec_mutex);
+       retval = mutex_lock_interruptible(&task->cred_guard_mutex);
        if (retval  < 0)
                goto out;
-
-       retval = -EPERM;
 repeat:
        /*
         * Nasty, nasty.
@@ -212,27 +203,28 @@ repeat:
                goto repeat;
        }
 
-       if (!task->mm)
-               goto bad;
-       /* the same process cannot be attached many times */
-       if (task->ptrace & PT_PTRACED)
-               goto bad;
        retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
        if (retval)
                goto bad;
 
-       /* Go */
+       retval = -EPERM;
+       if (unlikely(task->exit_state))
+               goto bad;
+       if (task->ptrace & PT_PTRACED)
+               goto bad;
+
        task->ptrace |= PT_PTRACED;
        if (capable(CAP_SYS_PTRACE))
                task->ptrace |= PT_PTRACE_CAP;
 
        __ptrace_link(task, current);
-
        send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
+
+       retval = 0;
 bad:
        write_unlock_irqrestore(&tasklist_lock, flags);
        task_unlock(task);
-       mutex_unlock(&task->cred_exec_mutex);
+       mutex_unlock(&task->cred_guard_mutex);
 out:
        return retval;
 }
@@ -304,6 +296,8 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
        if (child->ptrace) {
                child->exit_code = data;
                dead = __ptrace_detach(current, child);
+               if (!child->exit_state)
+                       wake_up_process(child);
        }
        write_unlock_irq(&tasklist_lock);