PTRACE_EVENT_SIGTRAP
Oleg Nesterov
oleg at redhat.com
Thu Oct 29 19:41:58 UTC 2009
On 10/27, Roland McGrath wrote:
>
> This is used only in the UTRACE_SIGNAL_HANDLER case. That means after
> tracehook_signal_handler(), which is where a signal handler has just
> been set up.
>
> For reference, in old ptrace, tracehook_signal_handler() is:
>
> if (stepping)
> ptrace_notify(SIGTRAP);
>
> This means that when PTRACE_SINGLE{STEP,BLOCK},signr was used to
> deliver the handled signal, we stop there in ptrace_notify. This is
> in lieu of a proper single-step trap, with the theory that what you
> meant to "step to" next was the first instruction of the signal
> handler, rather than the second instruction of the handler.
>
> The only purpose of PTRACE_EVENT_SIGTRAP is to distinguish this case
> from PTRACE_EVENT_SIGNAL as it would be for a real SIGTRAP after a
> normal instruction step. The only purposes of this distinction are to
> make PTRACE_SETSIGINFO have no effect, and to make resumptions ignore
> the data/signr argument. The former makes it consistent with other
> cases in utrace-ptrace that replace ptrace_notify() calls in the old
> ptrace, but that itself is a known nit incompatibility with the old
> behavior, so it's superfluous at best. The latter is just intended
> for pure bug-compatibility with the old behavior. Aside from these,
> there are no other reasons not to have the UTRACE_SIGNAL_HANDLER case
> result in PTRACE_EVENT_SIGNAL, with siginfo_t filled in to match what
> the old ptrace_notify() does.
>
> Is that all correct?
>
> In short, PTRACE_EVENT_SIGTRAP provides bug compatibility for
> PTRACE_SINGLESTEP,signr silently acting like PTRACE_SINGLESTEP,0 when
(s/PTRACE_SINGLESTEP/PTRACE_ANY/)
> called at the stop just provoked by the last PTRACE_SINGLESTEP,signr.
> Is that it?
Yes.
> I think this is a piece of bug compatibility that upstream will be
> happy to have "broken". That is, I bet most people don't realize at
> all PTRACE_SINGLESTEP,signr will sometimes swallow a signal after what
> appears to be a normal single-step stop. In fact, I suspect many
> might say that this is worse than the previous behavior my addition of
> this ptrace_notify() call (sometime before git so <2.6.12; Sep 2004,
> not sure what version that was, maybe 2.6.9). That behavior was that
> PTRACE_SINGLESTEP,signr would stop at the second instruction of the
> signal handler and never the first--but that would be a real step
> (like you now get after PTRACE_SINGLESTEP,0 when stopped in
> ptrace_notify() at the first instruction of the handler). I'm quite
> sure that at the time I never contemplated the signal-swallowing
> implication of using ptrace_notify() here.
>
> So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of
> UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look
> like a vanilla SIGTRAP and then fall into the default case for
> real signals.
Yes, I already thought about this. The patch is trivial, please see
below.
> Does that all sound right to you, or did I miss something?
Don't ask me, I never know what can be changed ;)
But yes, I agree. The current behaviour looks strange (if not wrong).
With this change ptrace(PTRACE_WHATEVER, signr) after PTRACE_SINGLESTEP
never ignores signr. Even if perhaps this is not really useful, this is
consistent. Afaics, this case was a single exception when ptrace(signr)
or PTRACE_SETSIGINFO) was ignored after PTRACE_SINGLESTEP.
The only problem with this change (if we do it now), it is always nice
to have a separate changelog to document the behaviour change. But
hopefully nobody cares, I mean, nobody will notice the difference.
Oleg.
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -73,7 +73,6 @@ struct ptrace_context {
#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16)
#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16)
-#define PTRACE_EVENT_SIGTRAP (3 << 16)
#define PTRACE_EVENT_SIGNAL (4 << 16)
/* events visible to user-space */
#define PTRACE_EVENT_MASK 0xFFFF
@@ -495,8 +494,8 @@ static u32 ptrace_report_signal(u32 acti
context->siginfo = NULL;
if (resume != UTRACE_RESUME) {
- set_stop_code(context, PTRACE_EVENT_SIGTRAP);
- return UTRACE_STOP | UTRACE_SIGNAL_IGN;
+ info->si_signo = SIGTRAO;
+ break;
}
case UTRACE_SIGNAL_REPORT:
@@ -509,21 +508,21 @@ static u32 ptrace_report_signal(u32 acti
return resume | resume_signal(task, context->signr,
info, return_ka);
- default:
- WARN_ON(context->siginfo);
- 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);
+ }
- context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo;
- context->signr = info->si_signo;
+ WARN_ON(context->siginfo);
+ 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);
- return UTRACE_STOP | UTRACE_SIGNAL_IGN;
- }
+ context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo;
+ context->signr = info->si_signo;
+
+ return UTRACE_STOP | UTRACE_SIGNAL_IGN;
}
static u32 ptrace_report_quiesce(u32 action,
More information about the utrace-devel
mailing list