* [PATCH 0/2] ptrace fixes for 3.2
@ 2012-01-04 16:28 Oleg Nesterov
2012-01-04 16:29 ` [PATCH 1/2] ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race Oleg Nesterov
2012-01-04 16:29 ` [PATCH 2/2] ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach Oleg Nesterov
0 siblings, 2 replies; 3+ messages in thread
From: Oleg Nesterov @ 2012-01-04 16:28 UTC (permalink / raw)
To: Linus Torvalds
Cc: Denys Vlasenko, Lukasz Michalik, Dmitry V. Levin, Tejun Heo,
linux-kernel, stable
Hello.
2 simple fixes for 3.2. Both changes are temporary hacks, hopefully
we will properly fix the problems in the next devel cycle.
Oleg.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race
2012-01-04 16:28 [PATCH 0/2] ptrace fixes for 3.2 Oleg Nesterov
@ 2012-01-04 16:29 ` Oleg Nesterov
2012-01-04 16:29 ` [PATCH 2/2] ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach Oleg Nesterov
1 sibling, 0 replies; 3+ messages in thread
From: Oleg Nesterov @ 2012-01-04 16:29 UTC (permalink / raw)
To: Linus Torvalds
Cc: Denys Vlasenko, Lukasz Michalik, Dmitry V. Levin, Tejun Heo,
linux-kernel, stable
Test-case:
int main(void)
{
int pid, status;
pid = fork();
if (!pid) {
for (;;) {
if (!fork())
return 0;
if (waitpid(-1, &status, 0) < 0) {
printf("ERR!! wait: %m\n");
return 0;
}
}
}
assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0);
assert(waitpid(-1, NULL, 0) == pid);
assert(ptrace(PTRACE_SETOPTIONS, pid, 0,
PTRACE_O_TRACEFORK) == 0);
do {
ptrace(PTRACE_CONT, pid, 0, 0);
pid = waitpid(-1, NULL, 0);
} while (pid > 0);
return 1;
}
It fails because ->real_parent sees its child in EXIT_DEAD state
while the tracer is going to change the state back to EXIT_ZOMBIE
in wait_task_zombie().
The offending commit is 823b018e which moved the EXIT_DEAD check,
but in fact we should not blame it. The original code was not
correct as well because it didn't take ptrace_reparented() into
account and because we can't really trust ->ptrace.
This patch adds the additional check to close this particular
race but it doesn't solve the whole problem. We simply can't
rely on ->ptrace in this case, it can be cleared if the tracer
is multithreaded by the exiting ->parent.
I think we should kill EXIT_DEAD altogether, we should always
remove the soon-to-be-reaped child from ->children or at least
we should never do the DEAD->ZOMBIE transition. But this is too
complex for 3.2.
Reported-and-tested-by: Denys Vlasenko <vda.linux@googlemail.com>
Tested-by: Lukasz Michalik <lmi@ift.uni.wroc.pl>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: <stable@kernel.org> [3.0+]
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/exit.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index d0b7d98..e6e01b9 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1540,8 +1540,15 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
}
/* dead body doesn't have much to contribute */
- if (p->exit_state == EXIT_DEAD)
+ if (unlikely(p->exit_state == EXIT_DEAD)) {
+ /*
+ * But do not ignore this task until the tracer does
+ * wait_task_zombie()->do_notify_parent().
+ */
+ if (likely(!ptrace) && unlikely(ptrace_reparented(p)))
+ wo->notask_error = 0;
return 0;
+ }
/* slay zombie? */
if (p->exit_state == EXIT_ZOMBIE) {
--
1.5.5.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach
2012-01-04 16:28 [PATCH 0/2] ptrace fixes for 3.2 Oleg Nesterov
2012-01-04 16:29 ` [PATCH 1/2] ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race Oleg Nesterov
@ 2012-01-04 16:29 ` Oleg Nesterov
1 sibling, 0 replies; 3+ messages in thread
From: Oleg Nesterov @ 2012-01-04 16:29 UTC (permalink / raw)
To: Linus Torvalds
Cc: Denys Vlasenko, Lukasz Michalik, Dmitry V. Levin, Tejun Heo,
linux-kernel, stable
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>
---
kernel/ptrace.c | 13 ++++++++++++-
kernel/signal.c | 2 --
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 24d0447..78ab24a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -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
diff --git a/kernel/signal.c b/kernel/signal.c
index b3f78d0..2065515 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1994,8 +1994,6 @@ static bool do_signal_stop(int signr)
*/
if (!(sig->flags & SIGNAL_STOP_STOPPED))
sig->group_exit_code = signr;
- else
- WARN_ON_ONCE(!current->ptrace);
sig->group_stop_count = 0;
--
1.5.5.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-01-04 16:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-04 16:28 [PATCH 0/2] ptrace fixes for 3.2 Oleg Nesterov
2012-01-04 16:29 ` [PATCH 1/2] ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race Oleg Nesterov
2012-01-04 16:29 ` [PATCH 2/2] ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach Oleg Nesterov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).