how does ptrace catch fork's system call?

1.7k views Asked by At

I try to use ptrace to catch child process system call id such as execve(11) or fork(2).

my code is here.

#include <sys/syscall.h>
#include <sys/reg.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main(){
    pid_t pid;
    if ((pid = fork()) == 0){
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        pid_t t = fork();
    } else{
        int status;
        struct rusage resource;
        while (true){
            wait4(pid, &status, 0, &resource);
            if (WIFEXITED(status)) break;
            int syscall = ptrace(PTRACE_PEEKUSER, pid, 4 * ORIG_EAX, NULL);
            if (syscall == SYS_execve) printf("%d\n", syscall);
            ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
        }
    }
    return 0;
}

In my opinion, the program should print "2" to screen(because system call "fork" id is 2), but I got nothing after the program finished. Can someone explain me about it?

2

There are 2 answers

1
doptimusprime On

If your program has exited normally, then

if (WIFEXITED(status)) break;

this statement might have caused not printing 2 as it is taking it out of the loop.

Please see this statement.

0
Antonis Paragioudakis On

Op probably doesn't need the answer now but someone else might so I will just put it out there.

First of all the line if (syscall == SYS_execve) will be valid only if you are executing the execv system call. This means it will print the system call number assigned to execv which in my machine (x86) is number 11. But you never actually call execv so nothing gets printed.

Secondly, the reason you probably will not see 2 getting printed on the screen is that if you are using version 2.3.3 or newer, then a fork() call isn't actually a system call. Instead of invoking the kernel's fork(), the glibc fork() wrapper function is invoked which really isn't a system call.

This function will then invoke the clone() system call. So you will need to search for the clone system call id (depending on the version you are using) or use SYS_clone, if you want to catch it and manipulate it.

source: http://man7.org/linux/man-pages/man2/fork.2.html