int ptrace_attach(struct task_struct *task)
 {
        int retval;
-       task_lock(task);
+
        retval = -EPERM;
        if (task->pid <= 1)
-               goto bad;
+               goto out;
        if (task->tgid == current->tgid)
-               goto bad;
+               goto out;
+
+       write_lock_irq(&tasklist_lock);
+       task_lock(task);
+
        /* the same process cannot be attached many times */
        if (task->ptrace & PT_PTRACED)
                goto bad;
                                      ? PT_ATTACHED : 0);
        if (capable(CAP_SYS_PTRACE))
                task->ptrace |= PT_PTRACE_CAP;
-       task_unlock(task);
 
-       write_lock_irq(&tasklist_lock);
        __ptrace_link(task, current);
-       write_unlock_irq(&tasklist_lock);
 
        force_sig_specific(SIGSTOP, task);
-       return 0;
 
 bad:
+       write_unlock_irq(&tasklist_lock);
        task_unlock(task);
+out:
        return retval;
 }
 
  */
 int ptrace_traceme(void)
 {
-       int ret;
+       int ret = -EPERM;
 
        /*
         * Are we already being traced?
         */
-       if (current->ptrace & PT_PTRACED)
-               return -EPERM;
-       ret = security_ptrace(current->parent, current);
-       if (ret)
-               return -EPERM;
-       /*
-        * Set the ptrace bit in the process ptrace flags.
-        */
-       current->ptrace |= PT_PTRACED;
-       return 0;
+       task_lock(current);
+       if (!(current->ptrace & PT_PTRACED)) {
+               ret = security_ptrace(current->parent, current);
+               /*
+                * Set the ptrace bit in the process ptrace flags.
+                */
+               if (!ret)
+                       current->ptrace |= PT_PTRACED;
+       }
+       task_unlock(current);
+       return ret;
 }
 
 /**