From: Oleg Nesterov <oleg@redhat.com>
To: Tejun Heo <tj@kernel.org>
Cc: roland@redhat.com, linux-kernel@vger.kernel.org,
torvalds@linux-foundation.org, akpm@linux-foundation.org,
rjw@sisk.pl, jan.kratochvil@redhat.com
Subject: Re: [PATCH 10/16] ptrace: clean transitions between TASK_STOPPED and TRACED
Date: Wed, 22 Dec 2010 12:39:48 +0100 [thread overview]
Message-ID: <20101222113948.GA30266@redhat.com> (raw)
In-Reply-To: <20101221173155.GE13285@htj.dyndns.org>
On 12/21, Tejun Heo wrote:
>
> On Mon, Dec 20, 2010 at 04:00:37PM +0100, Oleg Nesterov wrote:
> > > +
> > > + wait_on_bit(&child->group_stop, bit,
> >
> > Hmm. we could probably use ->wait_chldexit/__wake_up_parent instead,
> > although I am not sure this would be more clean...
>
> Hmmmm, I actually think that would be cleaner. I just didn't know it
> was there. Will convert over to it.
__wake_up_parent() needs tasklist to pin ->parent. But probably in
this particular case we can rely on rcu, or even ->siglock (given
that attach/detach take this lock too).
> > This doesn't work if ptrace_attach() races with clone(CLONE_STOPPED).
> > ptrace_check_attach() can return the wrong ESRCH after that. Perhaps
> > it is time to kill the CLONE_STOPPED code in do_fork().
>
> Ah, thanks for spotting it. I missed that. We should be able to
> convert it to call ptrace_stop(), right?
Perhaps... But then we should wakeup the new child. Perhaps we can
just kill that code, CLONE_STOPPED is deprecated and triggers the
warning since bdff746a (Feb 4 2008).
> > ptrace_check_attach()->wait_on_bit() logic fixes the previous example,
> > but:
> >
> > 1. the tracer knows that the tracee is stopped
> >
> > 2. the tracer does ptrace(ATTACH)
> >
> > 3. the tracer does do_wait()
> >
> > In this case do_wait() can see the tracee in TASK_RUNNING state,
> > this breaks wait_task_stopped(ptrace => true).
> >
> > Jan?
>
> I see. I can move the transition wait logic into PTRACE_ATTACH.
> Would that be good enough?
Yes, I thought about this too. But ptrace's semantics is really strange,
even if we move wait_on_bit() into ptrace_attach() we still have a
user-visible change.
sys_ptrace() only works for the single thread who did PTRACE_ATTACH,
but do_wait() should work for its sub-threads.
1. the tracer knows that the tracee is stopped
2. the tracer does ptrace(ATTACH)
3. the tracer's sub-thread does do_wait()
Note! Personally I think we can ignore this "problem", I do not
think it can break anything except some specialized test-case.
> This is also related to how to wait for attach completion for a new
> more transparent attach. Would it be better for such a request to
> make sure the operation to complete before returning or is it
> preferable to keep using wait(2) for that? We'll probably be able to
> share the transition wait logic with it. I think it would be better
> to return after the attach is actually complete but is there any
> reason that I'm missing which makes using wait(2) preferrable?
Oh, I do not know. This is the main problem with ptrace. You can
always understand what the code does, but you can never know what
was the supposed behaviour ;)
That is why I am asking Jan and Roland who understand the userland
needs.
Personally, I _think_ it makes sense to keep do_wait() working after
ptrace_attach(), if it is called by the thread which did attach.
But perhaps even this is not really important.
> @@ -1799,22 +1830,28 @@ static int do_signal_stop(int signr)
> > > */
> > > sig->group_exit_code = signr;
> > >
> > > - current->group_stop = gstop;
> > > + current->group_stop &= ~GROUP_STOP_SIGMASK;
> > > + current->group_stop |= signr | gstop;
> > > sig->group_stop_count = 1;
> > > - for (t = next_thread(current); t != current; t = next_thread(t))
> > > + for (t = next_thread(current); t != current;
> > > + t = next_thread(t)) {
> > > + t->group_stop &= ~GROUP_STOP_SIGMASK;
> > > /*
> > > * Setting state to TASK_STOPPED for a group
> > > * stop is always done with the siglock held,
> > > * so this check has no races.
> > > */
> > > if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) {
> > > - t->group_stop = gstop;
> > > + t->group_stop |= signr | gstop;
> > > sig->group_stop_count++;
> > > signal_wake_up(t, 0);
> > > - } else
> > > + } else {
> > > task_clear_group_stop(t);
> >
> > This looks racy. Suppose that "current" is ptraced, in this case
> > it can initiate the new group-stop even if SIGNAL_STOP_STOPPED
> > is set and we have another TASK_STOPPED thead T.
> >
> > Suppose that another (or same) debugger ataches to this thread T,
> > wakes it up and sets GROUP_STOP_TRAPPING.
> >
> > T resumes, calls ptrace_stop() in TASK_STOPPED, and temporary drops
> > ->siglock.
> >
> > Now, this task_clear_group_stop(T) confuses ptrace_check_attach(T).
> >
> > I think ptrace_stop() should be called in TASK_RUNNING state.
> > This also makes sense because we may call arch_ptrace_stop().
>
> I'm feeling a bit too dense to process the above right now. I'll
> respond to the above next morning after a strong cup of coffee. :-)
OK ;)
But look. Even if the race doesn't exist. ptrace_stop() can drop
->siglock and call arch_ptrace_stop() which can fault/sleep/whatever.
I think this doesn't really matter, but otoh it would be more clean
to do this in TASK_RUNNING state anyway. At least, in anny case
arch_ptrace_stop() can return in TASK_RUNNING.
> > > @@ -1842,7 +1879,18 @@ static int do_signal_stop(int signr)
> > >
> > > spin_lock_irq(¤t->sighand->siglock);
> > > } else
> > > - ptrace_stop(current->exit_code, CLD_STOPPED, 0, NULL);
> > > + ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK,
> > > + CLD_STOPPED, 0, NULL);
> >
> > Perhaps it would be more clean to clear ->exit_code here, in the
> > "else" branch.
>
> Hmmm... and dropping current->exit_code clearing from the
> do_signal_stop(), right? I'm a bit confused about the use of
> current->exit_code tho.
Oh, the right answer is: ptrace shouldn't use ->exit_code at all ;)
And its usage is very confusing.
> Why aren't we clearing it from ptrace_stop()?
ptrace_report_syscall() and ptrace_signal() check ->exit_code after
return from ptrace_stop(), otherwise we ignore the "data" argument
of ptrace_resume/ptrace_detach.
Oleg.
next prev parent reply other threads:[~2010-12-22 11:47 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-06 16:56 [PATCHSET] ptrace,signal: sane interaction between ptrace and job control signals, take#2 Tejun Heo
2010-12-06 16:56 ` [PATCH 01/16] signal: fix SIGCONT notification code Tejun Heo
2010-12-06 16:56 ` [PATCH 02/16] signal: fix CLD_CONTINUED notification target Tejun Heo
2010-12-20 14:58 ` Oleg Nesterov
2010-12-21 16:31 ` Tejun Heo
2010-12-06 16:56 ` [PATCH 03/16] signal: remove superflous try_to_freeze() loop in do_signal_stop() Tejun Heo
2010-12-20 14:59 ` Oleg Nesterov
2010-12-06 16:56 ` [PATCH 04/16] ptrace: kill tracehook_notify_jctl() Tejun Heo
2010-12-20 14:59 ` Oleg Nesterov
2010-12-21 17:00 ` Tejun Heo
2010-12-06 16:56 ` [PATCH 05/16] ptrace: add @why to ptrace_stop() Tejun Heo
2010-12-06 16:56 ` [PATCH 06/16] signal: fix premature completion of group stop when interfered by ptrace Tejun Heo
2010-12-20 15:00 ` Oleg Nesterov
2010-12-21 17:04 ` Tejun Heo
2010-12-06 16:56 ` [PATCH 07/16] signal: use GROUP_STOP_PENDING to stop once for a single group stop Tejun Heo
2010-12-06 16:56 ` [PATCH 08/16] ptrace: participate in group stop from ptrace_stop() iff the task is trapping for " Tejun Heo
2010-12-06 16:56 ` [PATCH 09/16] ptrace: make do_signal_stop() use ptrace_stop() if the task is being ptraced Tejun Heo
2010-12-23 12:26 ` Oleg Nesterov
2010-12-23 13:53 ` Tejun Heo
2010-12-23 16:06 ` Oleg Nesterov
2010-12-23 16:33 ` Tejun Heo
2011-01-17 22:09 ` Roland McGrath
2011-01-27 13:56 ` Tejun Heo
2011-01-28 20:30 ` Roland McGrath
2011-01-31 14:39 ` Tejun Heo
2010-12-06 16:56 ` [PATCH 10/16] ptrace: clean transitions between TASK_STOPPED and TRACED Tejun Heo
2010-12-20 15:00 ` Oleg Nesterov
2010-12-21 17:31 ` Tejun Heo
2010-12-21 17:32 ` Tejun Heo
2010-12-22 10:54 ` Tejun Heo
2010-12-22 11:39 ` Oleg Nesterov [this message]
2010-12-22 15:14 ` Tejun Heo
2010-12-22 16:00 ` Oleg Nesterov
2010-12-22 16:21 ` Tejun Heo
2010-12-06 16:56 ` [PATCH 11/16] signal: prepare for CLD_* notification changes Tejun Heo
2010-12-20 16:21 ` Oleg Nesterov
2010-12-20 16:23 ` Oleg Nesterov
2010-12-21 17:35 ` Tejun Heo
2010-12-06 16:57 ` [PATCH 12/16] ptrace: make group stop notification reliable against ptrace Tejun Heo
2010-12-20 17:34 ` Oleg Nesterov
2010-12-21 17:43 ` Tejun Heo
2010-12-22 11:54 ` Oleg Nesterov
2010-12-22 15:26 ` Tejun Heo
2010-12-22 16:02 ` Oleg Nesterov
2010-12-06 16:57 ` [PATCH 13/16] ptrace: reorganize __ptrace_unlink() and ptrace_untrace() Tejun Heo
2010-12-20 18:15 ` Oleg Nesterov
2010-12-21 17:54 ` Tejun Heo
2010-12-06 16:57 ` [PATCH 14/16] ptrace: make SIGCONT notification reliable against ptrace Tejun Heo
2010-12-20 19:43 ` Oleg Nesterov
2010-12-21 17:48 ` Tejun Heo
2010-12-22 12:16 ` Oleg Nesterov
2010-12-21 17:25 ` Oleg Nesterov
2010-12-22 10:35 ` Tejun Heo
2010-12-06 16:57 ` [PATCH 15/16] ptrace: make sure SIGNAL_NOTIFY_CONT is checked after ptrace_signal() Tejun Heo
2010-12-06 16:57 ` [PATCH 16/16] ptrace: remove the extra wake_up_process() from ptrace_detach() Tejun Heo
2010-12-07 0:10 ` Roland McGrath
2010-12-07 13:43 ` Tejun Heo
2010-12-21 17:54 ` Oleg Nesterov
2010-12-22 10:36 ` Tejun Heo
2010-12-14 17:36 ` [PATCHSET] ptrace,signal: sane interaction between ptrace and job control signals, take#2 Oleg Nesterov
2010-12-14 17:46 ` Tejun Heo
2010-12-22 15:20 ` Oleg Nesterov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101222113948.GA30266@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=jan.kratochvil@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=roland@redhat.com \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.