Wait for PTRACE_SYSCALL after mid-syscall PTRACE_EVENTs
authorJosh Stone <jistone@redhat.com>
Thu, 7 Nov 2013 23:25:06 +0000 (15:25 -0800)
committerJosh Stone <jistone@redhat.com>
Wed, 13 Nov 2013 00:40:57 +0000 (16:40 -0800)
commitb89ea1d19677fa0dd9c605ef492c5f6dabf15752
treeadc9e25def60c29b414b36d366ab787fee7a9ef8
parent111e701af52ade094648ed058890f5b3c20853ea
Wait for PTRACE_SYSCALL after mid-syscall PTRACE_EVENTs

It is found that PTRACE_EVENT_FORK, _CLONE, and _EXEC all trigger in the
middle of the syscall in question.  It is not safe to modify the mutatee
at this point, because the syscall return value may not be written into
registers yet.

For instance, test4_2 does some post-fork instrumentation on the parent,
which triggers an iRPC on x86_64.  To run the iRPC, the process state is
saved, state is overwritten to setup the iRPC, process continues, then
state is restored.  When the syscall return value isn't written until
that continue, then it will be lost and we've saved+restored the wrong
value.  This results in test4_2 reporting "fork result: 56" (SYS_clone),
or it may even get -1 and errno=ENOSYS if syscall auditing is enabled.

The exact symptom is kernel-dependent.  The utrace-patched ptrace on
RHEL6 actually did wait to fire the event until after the fork result
was written, so it had no problem.  RHEL5 and Fedora 19 do show the bad
fork result though.

The solution is to create a new "postponed syscall" state, and resume
the process with PTRACE_SYSCALL to finish up the syscall related to the
PTRACE_EVENT first.  Only then is the event actually processed and
callbacks are delivered as needed.
proccontrol/h/Event.h
proccontrol/h/EventType.h
proccontrol/src/event.C
proccontrol/src/handler.C
proccontrol/src/int_handler.h
proccontrol/src/int_process.h
proccontrol/src/linux.C
proccontrol/src/linux.h
proccontrol/src/process.C