0

I'm trying to monitor/redirect syscalls in my own process. LD_PRELOAD doesn't work when fwrite calls write inside libc, and got/plt hooks seem to have the same problem. I'm looking for a solution based on ptrace, but I can't fork() and run the main app as a child because the app communicates with its parent via signals.

There is a thread from 2006 that suggests the tracer can be on a thread group that's different from the tracee, but it doesn't seem to work in practice: http://yarchive.net/comp/linux/ptrace_self_attach.html

pid = fork();
if (pid == 0) {
    prctl(PR_SET_PTRACER, getppid());
    raise(SIGSTOP);
} else {
    sleep(1);
    ptrace(PTRACE_SEIZE, pid, NULL, NULL);
    for (;;) {
        int status;
        int ret = waitpid(pid, &status, 0);
        warn("wait=%d:", ret);
        ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
        warn("ptrace=%d:", ret);        
    }
}

The problem I'm facing is that ptrace(PTRACE_SYSCALL) expects the tracee to be in ptrace-wait state, i.e. it must have raised SIGSTOP and the tracer needs to wait() for it. Since the relation is inversed in this case (tracer is the child of the tracee) PTRACE_SYSCALL returns ESRCH.

How does strace get away with tracing an existing pid ?

patraulea
  • 652
  • 2
  • 5
  • 26

1 Answers1

0

I'm a bit unclear on what exactly you're asking here. It sounds like you have the attaching part resolved (which is the most difficult problem to resolve). If that is the case, then getting the process to stop is not a problem. Just send the process a signal. The process will stop and send you a TRAP so you can decide what to do with the signal. At this point you can call ptrace(PTRACE_SYSCALL, pid, 0, 0). This will both start it in SYSCALL trace mode, and prevent your signal from arriving at the debugee (thus not introducing unexpected signals into the process).

Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57