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 ?