[PATCH] Try to use PTRACE_SETOPTIONS to handle non-ptrace SIGTRAP
Roland McGrath
roland at redhat.com
Fri Jul 23 01:12:14 UTC 2010
> diff --git a/process.c b/process.c
> index dadf830..ff78ff0 100644
> --- a/process.c
> +++ b/process.c
> @@ -1732,9 +1732,10 @@ struct tcb *tcp;
> fixvfork(tcp);
> #endif /* SUNOS4 */
> #if defined LINUX && defined TCB_WAITEXECVE
> - if (exiting(tcp) && syserror(tcp))
> - tcp->flags &= ~TCB_WAITEXECVE;
> - else
> + if (exiting(tcp)) {
> + if (syserror(tcp))
> + tcp->flags &= ~TCB_WAITEXECVE;
> + } else
This code needs comments. Furthermore, the actual behavior of Linux
kernels where TCB_WAITEXECVE is needed (i.e. PTRACE_O_TRACEEXEC not
supported or not yet in force) is that a normal SIGTRAP signal is
generated, so the normal ptrace signal stop for that comes only after
the syscall-exit stop for the execve call completing. Hence, even
before the PTRACE_O_TRACEEXEC support, we should change this code to
only ever set TCB_WAITEXECVE in the first place with:
if (exiting(tcp) && !syserror(tcp))
> +#ifdef USE_PTRACE_SETOPTIONS
> +
> +static int use_ptrace_setoptions = 1;
> +static int probe_ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
These variables need comments explaining their meanings.
Also, I don't see a reason for having use_ptrace_setoptions.
The (probe_ptrace_setoptions == 0) test looks sufficient for the tests.
> + /* Ignore post-execve trap. */
> + if (is_post_execve_trap(tcp, status)) {
> +#ifdef TCB_WAITEXECVE
> + tcp->flags &= ~TCB_WAITEXECVE;
> +#endif
> + goto tracing;
> + }
Perhaps the flag magic should go inside is_post_execve_trap too.
> +is_ptrace_stop(struct tcb *tcp, int status)
> +{
> + if (tcp->flags & TCB_STARTUP)
> + /* Didn't have the chance to set ptrace options yet. */
> + return WSTOPSIG(status) == SIGTRAP;
When internal_fork forces CLONE_PTRACE (or later if we start using
PTRACE_O_TRACE{CLONE,FORK,VFORK}, same thing), the new child inherits
the PTRACE_O_* settings from its creator. So it doesn't need to get a
PTRACE_SETOPTIONS call at all, in fact.
The set_ptrace_options call could be conditional on tcp->parent == NULL
to cover that, I think. Note that makes it consistent with the case
where the child reports before the parent syscall-exit report, where
internal_fork will then notice the TCB_SUSPENDED child--but you didn't
add a set_ptrace_options call there (as, indeed, it's not needed).
The code of course should get some comments about this subtlety.
This might be relevant in is_ptrace_stop too. But, in fact the child
seen first doesn't get TCB_STARTUP, so I guess it will in fact be
understood correctly.
Thanks,
Roland
More information about the Strace-devel
mailing list