Skip to content

Commit 8a88951

Browse files
oleg-nesterovtorvalds
authored andcommitted
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. Acked-by: Tejun Heo <[email protected]> Cc: <[email protected]> [3.1] Signed-off-by: Oleg Nesterov <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 50b8d25 commit 8a88951

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

kernel/ptrace.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,20 @@ void __ptrace_unlink(struct task_struct *child)
9696
*/
9797
if (!(child->flags & PF_EXITING) &&
9898
(child->signal->flags & SIGNAL_STOP_STOPPED ||
99-
child->signal->group_stop_count))
99+
child->signal->group_stop_count)) {
100100
child->jobctl |= JOBCTL_STOP_PENDING;
101101

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+
102113
/*
103114
* If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
104115
* @child in the butt. Note that @resume should be used iff @child

kernel/signal.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,8 +1994,6 @@ static bool do_signal_stop(int signr)
19941994
*/
19951995
if (!(sig->flags & SIGNAL_STOP_STOPPED))
19961996
sig->group_exit_code = signr;
1997-
else
1998-
WARN_ON_ONCE(!current->ptrace);
19991997

20001998
sig->group_stop_count = 0;
20011999

0 commit comments

Comments
 (0)