aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/ptrace.c59
1 files changed, 39 insertions, 20 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index e6098434b533..43485866749a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -41,7 +41,26 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
41 * __ptrace_unlink - unlink ptracee and restore its execution state 41 * __ptrace_unlink - unlink ptracee and restore its execution state
42 * @child: ptracee to be unlinked 42 * @child: ptracee to be unlinked
43 * 43 *
44 * Remove @child from the ptrace list, move it back to the original parent. 44 * Remove @child from the ptrace list, move it back to the original parent,
45 * and restore the execution state so that it conforms to the group stop
46 * state.
47 *
48 * Unlinking can happen via two paths - explicit PTRACE_DETACH or ptracer
49 * exiting. For PTRACE_DETACH, unless the ptracee has been killed between
50 * ptrace_check_attach() and here, it's guaranteed to be in TASK_TRACED.
51 * If the ptracer is exiting, the ptracee can be in any state.
52 *
53 * After detach, the ptracee should be in a state which conforms to the
54 * group stop. If the group is stopped or in the process of stopping, the
55 * ptracee should be put into TASK_STOPPED; otherwise, it should be woken
56 * up from TASK_TRACED.
57 *
58 * If the ptracee is in TASK_TRACED and needs to be moved to TASK_STOPPED,
59 * it goes through TRACED -> RUNNING -> STOPPED transition which is similar
60 * to but in the opposite direction of what happens while attaching to a
61 * stopped task. However, in this direction, the intermediate RUNNING
62 * state is not hidden even from the current ptracer and if it immediately
63 * re-attaches and performs a WNOHANG wait(2), it may fail.
45 * 64 *
46 * CONTEXT: 65 * CONTEXT:
47 * write_lock_irq(tasklist_lock) 66 * write_lock_irq(tasklist_lock)
@@ -55,25 +74,25 @@ void __ptrace_unlink(struct task_struct *child)
55 list_del_init(&child->ptrace_entry); 74 list_del_init(&child->ptrace_entry);
56 75
57 spin_lock(&child->sighand->siglock); 76 spin_lock(&child->sighand->siglock);
58 if (task_is_traced(child)) { 77
59 /* 78 /*
60 * If group stop is completed or in progress, it should 79 * Reinstate GROUP_STOP_PENDING if group stop is in effect and
61 * participate in the group stop. Set GROUP_STOP_PENDING 80 * @child isn't dead.
62 * before kicking it. 81 */
63 * 82 if (!(child->flags & PF_EXITING) &&
64 * This involves TRACED -> RUNNING -> STOPPED transition 83 (child->signal->flags & SIGNAL_STOP_STOPPED ||
65 * which is similar to but in the opposite direction of 84 child->signal->group_stop_count))
66 * what happens while attaching to a stopped task. 85 child->group_stop |= GROUP_STOP_PENDING;
67 * However, in this direction, the intermediate RUNNING 86
68 * state is not hidden even from the current ptracer and if 87 /*
69 * it immediately re-attaches and performs a WNOHANG 88 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
70 * wait(2), it may fail. 89 * @child in the butt. Note that @resume should be used iff @child
71 */ 90 * is in TASK_TRACED; otherwise, we might unduly disrupt
72 if (child->signal->flags & SIGNAL_STOP_STOPPED || 91 * TASK_KILLABLE sleeps.
73 child->signal->group_stop_count) 92 */
74 child->group_stop |= GROUP_STOP_PENDING; 93 if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child))
75 signal_wake_up(child, 1); 94 signal_wake_up(child, task_is_traced(child));
76 } 95
77 spin_unlock(&child->sighand->siglock); 96 spin_unlock(&child->sighand->siglock);
78} 97}
79 98