ptrace: SIGTRAP and EXIT race

Robert Ayrapetyan robert.ayrapetyan at gmail.com
Sat Feb 23 16:02:45 UTC 2019


raise(SIGSTOP) is not necessary - child stops by itself on the first
instruction after execve.

Let's see what's in these 700 lines of code:

Read\Write memory (this is for Add\Remove breakpoints);
TrapWait (main debugger cycle, handles threads born\destroy);
Init\Launch\Attach - this is all necessary to bootstrap;
GetNumLwps\GetLwpList - misc, you can't work with threads without these;
Step\Continue - self explanatory, you can't reproduce BP issue without
these functions;
GetRegs\SetRegs\GetEip\SetEip - all are needed for handling logic around
BPs.

That's it! There is one more function - EntryPoint, it just retrieves the
entry point from executable, you can ignore it.

If you can do the same using less amount of code (with all error checks in
place) - perfect, but I'm afraid it will not be less than 500 lines. So if
you don't like - just don't do that, no one can force you to lol.

Thanks!

On Sat, Feb 23, 2019 at 3:32 AM Konstantin Belousov <kostikbel at gmail.com>
wrote:

> On Fri, Feb 22, 2019 at 03:57:49PM -0800, Robert Ayrapetyan wrote:
> > Hi, thanks for a prompt reply. Here are the instructions of how to
> > reproduce (sorry for inconvenient way of specifying BP address when
> running
> > app):
> >
> > uname -a
> > FreeBSD XXX 12.0-RELEASE-p3 FreeBSD 12.0-RELEASE-p3 GENERIC  amd64
> >
> > cd /tmp
> > git clone https://github.com/rayrapetyan/ptrace_bug_poc.git
> > cd ptrace_bug_poc
> > mkdir build
> > cd build
> > cmake ..
> > make
> >
> > Run ~20 times:
> >
> > /tmp/ptrace_bug_poc/build/src/ptrace_test/ptrace_test
> > /tmp/ptrace_bug_poc/build/src/mt_example/mt_example 0x201385
> >
> > -------
> > Note: make sure 0x201385 is a call to <printf at plt> in
> > "/tmp/ptrace_bug_poc/build/src/mt_example/mt_example":
> > gdb /tmp/ptrace_bug_poc/build/src/mt_example/mt_example
> > disassemble foo
> > -------
> >
> > Wait fo appearance of:
> > "BOOM! Invalid BP hits counter (hits: 1, tid: XXXX)"
> > at the end of the output (most of the times it will be "SUCCESS")
> >
>
> ~700 lines of C++ code definitely do not fall under the 'minimal repro'
> spec.  I do not to read all of it.
>
> From looking at Debugger::Launch(), it seems that you missed the
> required debugger/child synchronization for PT_TRACE_ME. Typically child
> does
>         raise(SIGSTOP);
> immediately after PT_TRACE_ME, and the tracer must consume this signal.
> Otherwise the child continues the execution and might just execute the
> place where you intend to set a breakpoint. I may missed the sync (or it
> might be done by other means in your code), because as I said, I do not
> want to read 700 lines of C++.
>
>


More information about the freebsd-hackers mailing list