From: Salman Qazi <sqazi@google.com>
To: Oleg Nesterov <oleg@redhat.com>
Cc: taviso@google.com, Roland Dreier <rolandd@cisco.com>,
Andrew Morton <akpm@linux-foundation.org>,
Roland McGrath <roland@redhat.com>,
linux-kernel@vger.kernel.org
Subject: Re: Race in ptrace.
Date: Thu, 11 Feb 2010 08:32:14 -0800 [thread overview]
Message-ID: <4352991a1002110832j1a4e6680scf4aa7effeb83a75@mail.gmail.com> (raw)
In-Reply-To: <20100211125607.GA5086@redhat.com>
On Thu, Feb 11, 2010 at 4:56 AM, Oleg Nesterov <oleg@redhat.com> wrote:
> On 02/10, Salman Qazi wrote:
>>
>> I have
>> made a simpler version of tavis's test case:
>
> Thanks, now I see what you mean.
>
> But this all is correct, you can't expect PTRACE_SYSCALL can succeed
> is the tracee is running, it must be stopped or traced.
>
> The tracee is running because it was TASK_STOPPED and antagonist()
> sends SIGCONT.
>
> The tracee was TASK_STOPPED because the tracer passes sig = SIGSTOP
> via ptrace(PTRACE_SYSCALL, WSTOPSIG(status).
>
> Where do you see the bug?
Shouldn't ptrace(PTRACE_SYSCALL, WSTOPSIG(status)...), cause any
future signals to the child be intercepted by the parent?
>
> OK, let me simplify the test-case even more:
>
> int main(void)
> {
> int stat, ret;
> int pid = fork();
>
> if (!pid) {
> ptrace(PTRACE_TRACEME, 0, NULL, NULL);
> for (;;)
> ;
> }
>
> sleep(1); // wait for PTRACE_TRACEME
> kill(pid, SIGSTOP);
>
> // the child reports SIGSTOP, it is TASK_TRACED
> assert(pid == wait(&stat) && WIFSTOPPED(stat));
>
> // the tracee should stop, we pass sig = SIGSTOP
> assert(ptrace(PTRACE_SYSCALL, pid, 0, WSTOPSIG(stat)) == 0);
>
> // the child reports the group stop, it is TASK_STOPPED
> assert(pid == wait(&stat) && WIFSTOPPED(stat));
>
> // the tracee is STOPPED as requested, not TRACED,
> // SIGCONT wakes it up
> kill(pid, SIGCONT);
According to the man page, any signals to the
process are supposed to be intercepted by the parent and that is how
one is supposed to be able to control which signals make it to the
child. I am not sure if it makes any difference if the signal
originates at the parent. But in our test case, it doesn't. So, why
doesn't the parent get a notification first?
>
> // now the tracee is _running_, and PTRACE_SYSCALL must fail
> ret = ptrace(PTRACE_SYSCALL, pid, 0, WSTOPSIG(stat));
> printf("should fail: ret=%d %m\n", ret);
>
> return 0;
> }
>
> PTRACE_SYSCALL fails, and this is absolutely correct.
>
> Now, let's look at your test-case
>
>> int main(int argc, char **argv)
>> {
>> int status;
>> assert((child_pid = do_fork(child)) > 0);
>> assert((ant_pid = do_fork(antagonist)) > 0);
>> waitpid(child_pid, &status, 0);
>> ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL);
>> while(1) {
>> if (waitpid(child_pid, &status, 0) <= 0) {
>> printf("Errno %d\n", errno);
>> exit(EXIT_FAILURE);
>> }
>> if (WIFSTOPPED(status)) {
>
> WSTOPSIG() should be either SIGCONT or SIGSTOP
>
>> printf("stopped: %d\n", WSTOPSIG(status));
>>
>> /* This should work, but sometimes it doesn't */
>> if (ptrace(PTRACE_SYSCALL, child_pid,
>> NULL, WSTOPSIG(status)) < 0) {
>
> This should not work if the tracee reported the group stop (not the
> fact it dequeued SIGSTOP) and antagonist() sends SIGCONT in between.
>
>> /* Oddly it works the second time! */
>> assert (ptrace(PTRACE_SYSCALL,
>> child_pid, NULL, WSTOPSIG(status)) < 0);
>
> Of couse, it _can_ work the second time, antagonist() sends a signal
> (SIGCONT or SIGSTOP), the tracee dequeues the signal, and stops to
> report this signal.
>
> See?
>
> Oleg.
>
>
next prev parent reply other threads:[~2010-02-11 16:32 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-08 22:16 Salman Qazi
[not found] ` <20100208143231.6d804590.akpm@linux-foundation.org>
2010-02-09 11:27 ` Oleg Nesterov
2010-02-10 13:35 ` Oleg Nesterov
2010-02-10 18:38 ` Salman Qazi
2010-02-11 12:56 ` Oleg Nesterov
2010-02-11 16:32 ` Salman Qazi [this message]
2010-02-11 16:50 ` Oleg Nesterov
2010-02-11 18:43 ` Salman Qazi
2010-02-11 18:55 ` Oleg Nesterov
2010-02-11 19:08 ` Salman Qazi
2010-02-11 20:10 ` Oleg Nesterov
2010-02-11 20:39 ` Salman Qazi
2010-02-11 20:55 ` Roland McGrath
2010-02-11 21:05 ` Salman Qazi
2010-02-11 20:59 ` Oleg Nesterov
-- strict thread matches above, loose matches on Subject: below --
2010-02-08 22:04 Salman Qazi
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=4352991a1002110832j1a4e6680scf4aa7effeb83a75@mail.gmail.com \
--to=sqazi@google.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=roland@redhat.com \
--cc=rolandd@cisco.com \
--cc=taviso@google.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®