On 10/07, Roland McGrath wrote:
>
> > +   if (context->siginfo)
> > +           return ptrace_rw_siginfo(tracee, context, info, false);
> >
> > -   return error;
> > +   memset(info, 0, sizeof(*info));
> > +   info->si_signo = SIGTRAP;
> > +   info->si_code = context->ev_code; // XXX: ev_code was already cleared!!!
> > +   info->si_pid = task_pid_vnr(tracee);
> > +   info->si_uid = task_uid(tracee);
>
> Put that logic inside ptrace_rw_siginfo and call it unconditionally.

(and from the next review of PATCH 64)

> Then both helpers have everything in common, and they are static anyway,
> so you might as well just call ptrace_rw_siginfo from ptrace_request.

I mostly agree, but I'd like to keep this helper for now. I am not sure
yet, but perhaps it will be needed if we change detach to play with
ptrace_utrace_detached_ops. This was a reason why I added the separate
helper. But let me repeat I am not sure it will be really needed.

> It's
> going to check context->siginfo anyway.  The forged info is a wrong lie if
> it's actually clear because it was set and then there was a SIGKILL, but we
> can't tell the difference so a race could yield that bogon anyway.

Yes. I swear, I was going to do

        if (get_stop_code() == PTRACE_EVENT_SIGNAL)
                return ptrace_rw_siginfo();

instead, not sure why I used ->siginfo != NULL.

This way, when we call ptrace_rw_siginfo() we know that ->siginfo
must be valid. But if we race with SIGKILL and ->siginfo was not
cleared yet we can return the wrong info which was filled by the
next dequeue_signal().

I'll recheck this, but looks like we have anotrher reason for
fatal_signal_pending() in ptrace_rw_siginfo().

Or, we can change ptrace_report_signal() (or even utrace_get_signal())
to check __fatal_signal_pending().

> Where exactly does ->siginfo get cleared in that case?  I only see it
> cleared in the UTRACE_SIGNAL_REPORT case.  But SIGKILL should not do any
> signal reports, it bypasses them and you might get only the DEATH event.

It does, or I missed something.

Yes, if utrace_get_signal() dequeues SIGKILL it doesn't report and
just returns.

But, ptrace_report_signal() does:

                context->siginfo = info;
                /*
                 * context->siginfo points to the caller's stack.
                 * Make sure the subsequent UTRACE_SIGNAL_REPORT clears
                 * ->siginfo before return from get_signal_to_deliver().
                 */
                utrace_control(task, engine, UTRACE_INTERRUPT);

this means that, even if killed, the tracee will call utrace_get_signal()
with utrace->interrupt == T. In this case UTRACE_SIGNAL_REPORT will be
reported anyway.

Right?

Oleg.

Reply via email to