Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <tj@kernel.org>
Cc: <stable@kernel.org> [3.1]
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Oleg Nesterov and committed by
Linus Torvalds
8a88951b 50b8d257

+12 -3
+12 -1
kernel/ptrace.c
··· 96 96 */ 97 97 if (!(child->flags & PF_EXITING) && 98 98 (child->signal->flags & SIGNAL_STOP_STOPPED || 99 - child->signal->group_stop_count)) 99 + child->signal->group_stop_count)) { 100 100 child->jobctl |= JOBCTL_STOP_PENDING; 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 + } 101 112 102 113 /* 103 114 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
-2
kernel/signal.c
··· 1994 1994 */ 1995 1995 if (!(sig->flags & SIGNAL_STOP_STOPPED)) 1996 1996 sig->group_exit_code = signr; 1997 - else 1998 - WARN_ON_ONCE(!current->ptrace); 1999 1997 2000 1998 sig->group_stop_count = 0; 2001 1999