Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[deliverable/linux.git] / kernel / ptrace.c
index 24d04477b2575f0239782cf6287298a47d50f48c..00ab2ca5ed1179c941d15b9e002d3cacee780414 100644 (file)
@@ -96,9 +96,20 @@ void __ptrace_unlink(struct task_struct *child)
         */
        if (!(child->flags & PF_EXITING) &&
            (child->signal->flags & SIGNAL_STOP_STOPPED ||
-            child->signal->group_stop_count))
+            child->signal->group_stop_count)) {
                child->jobctl |= JOBCTL_STOP_PENDING;
 
+               /*
+                * This is only possible if this thread was cloned by the
+                * traced task running in the stopped group, set the signal
+                * for the future reports.
+                * FIXME: we should change ptrace_init_task() to handle this
+                * case.
+                */
+               if (!(child->jobctl & JOBCTL_STOP_SIGMASK))
+                       child->jobctl |= SIGSTOP;
+       }
+
        /*
         * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
         * @child in the butt.  Note that @resume should be used iff @child
@@ -161,6 +172,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
        return ret;
 }
 
+static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
+{
+       if (mode & PTRACE_MODE_NOAUDIT)
+               return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
+       else
+               return has_ns_capability(current, ns, CAP_SYS_PTRACE);
+}
+
 int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        const struct cred *cred = current_cred(), *tcred;
@@ -187,7 +206,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
             cred->gid == tcred->sgid &&
             cred->gid == tcred->gid))
                goto ok;
-       if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE))
+       if (ptrace_has_cap(tcred->user->user_ns, mode))
                goto ok;
        rcu_read_unlock();
        return -EPERM;
@@ -196,7 +215,7 @@ ok:
        smp_rmb();
        if (task->mm)
                dumpable = get_dumpable(task->mm);
-       if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE))
+       if (!dumpable  && !ptrace_has_cap(task_user_ns(task), mode))
                return -EPERM;
 
        return security_ptrace_access_check(task, mode);
@@ -266,7 +285,7 @@ static int ptrace_attach(struct task_struct *task, long request,
        task->ptrace = PT_PTRACED;
        if (seize)
                task->ptrace |= PT_SEIZED;
-       if (task_ns_capable(task, CAP_SYS_PTRACE))
+       if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
                task->ptrace |= PT_PTRACE_CAP;
 
        __ptrace_link(task, current);
This page took 0.028132 seconds and 5 git commands to generate.