History

ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach

This is the temporary simple fix for 3.2, we need more changes in this area. 1. do_signal_stop() assumes that the running untraced thread in the stopped thread group is not possible. This was our goal but it is not yet achieved: a stopped-but-resumed tracee can clone the running thread which can initiate another group-stop. Remove WARN_ON_ONCE(!current->ptrace). 2. A new thread always starts with ->jobctl = 0. If it is auto-attached and this group is stopped, __ptrace_unlink() sets JOBCTL_STOP_PENDING but JOBCTL_STOP_SIGMASK part is zero, this triggers WANR_ON(!signr) in do_jobctl_trap() if another debugger attaches. Change __ptrace_unlink() to set the artificial SIGSTOP for report. Alternatively we could change ptrace_init_task() to copy signr from current, but this means we can copy it for no reason and hide the possible similar problems.

Oleg Nesterov committed 14 years ago

Commit 8a889511 parent 50b8d252 files · +12 −3Browse files

Unified · Split

2 files
  1. kernel/ptrace.c +12 −1
  2. kernel/signal.c +0 −2
kernel/ptrace.c+12−1
@@ -96,9 +96,20 @@ void __ptrace_unlink(struct task_struct *child) · 95 unmodified lines
96 */96 */
97 if (!(child->flags & PF_EXITING) &&97 if (!(child->flags & PF_EXITING) &&
98 (child->signal->flags & SIGNAL_STOP_STOPPED ||98 (child->signal->flags & SIGNAL_STOP_STOPPED ||
99 child->signal->group_stop_count))99 child->signal->group_stop_count)) {
100 child->jobctl |= JOBCTL_STOP_PENDING;100 child->jobctl |= JOBCTL_STOP_PENDING;
101 101
102 /*
103 * This is only possible if this thread was cloned by the
104 * traced task running in the stopped group, set the signal
105 * for the future reports.
106 * FIXME: we should change ptrace_init_task() to handle this
107 * case.
108 */
109 if (!(child->jobctl & JOBCTL_STOP_SIGMASK))
110 child->jobctl |= SIGSTOP;
111 }
112
102 /*113 /*
103 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick114 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
104 * @child in the butt. Note that @resume should be used iff @child115 * @child in the butt. Note that @resume should be used iff @child
kernel/signal.c+0−2
@@ -1994,8 +1994,6 @@ static bool do_signal_stop(int signr) · 1993 unmodified lines
1994 */1994 */
1995 if (!(sig->flags & SIGNAL_STOP_STOPPED))1995 if (!(sig->flags & SIGNAL_STOP_STOPPED))
1996 sig->group_exit_code = signr;1996 sig->group_exit_code = signr;
1997 else
1998 WARN_ON_ONCE(!current->ptrace);
1999 1997
2000 sig->group_stop_count = 0;1998 sig->group_stop_count = 0;
2001 1999