Bug in setbpt/clearbpt for SPARC/SPARC64?

Denys Vlasenko dvlasenk at redhat.com
Tue Feb 5 13:29:40 UTC 2013


On 11/28/2012 02:14 PM, James Hogan wrote:
> Hi
> 
> While implementing regset support in strace for the metag architecture,
> I think I've noticed a problem in util.c.
> 
> For SPARC/SPARC64, arg_setup and arg_finish_change are defined to use
> PTRACE_GETREGS and PTRACE_SETREGS. However change_syscall also does a
> read-modify-write using PTRACE_GETREGS and PTRACE_SETREGS.
> 
> These are then combined in a bad way in setbpt:
> 
> if (arg_setup(tcp, &state) < 0
> /* reads the registers into state */
>     || get_arg0(tcp, &state, &tcp->inst[0]) < 0
>     || get_arg1(tcp, &state, &tcp->inst[1]) < 0
> /* reads arguments from state */
>     || change_syscall(tcp, clone_scno[current_personality]) < 0
> /* reads registers again, and changes one of them */
>     || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
>     || set_arg1(tcp, &state, 0) < 0
> /* sets argument registers in state */
>     || arg_finish_change(tcp, &state) < 0)
> /* writes back state, presumably undoing change_syscall's hard work. */
> 
> Looking at a "git diff v4.7..master util.c", it looks like clearbpt is
> doing something similar too.
> 
> Is that analysis correct or have I missed something important that would
> make it work?

setbpt/clearbpt is not supposed to be used when run on any non-ancient
Linux kernel. It was a hack used to work around problems with attaching
to forked children. Now kernel catches them for us:

static void
internal_fork(struct tcb *tcp)
{
        if ((ptrace_setoptions
            & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
           == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
                return;
...
        if (entering(tcp)) {
...
                setbpt(tcp); <---- The only use of setbpt()

-- 
vda




More information about the Strace-devel mailing list