Search code examples
cptrace

Why does ptrace not recognize the function?


I can't figure out why the function returns an "No such process" error message every time I run it, but simply using the same instructions inline produces the required output.

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void getregs(pid_t proc, struct user_regs_struct *regs);

int main() {
        pid_t proc = fork();

        if(proc == 0) {
                if(ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
                       perror("traceme");
                       exit(0);
                }

                if(execl("child", "child", NULL) == -1) {
                       perror("execl");
                       exit(0);
                }
        } else {
                wait(&proc);
                struct user_regs_struct regs;
                ptrace(PTRACE_GETREGS, proc, NULL, &regs);
                printf("eax: %08x\n", (unsigned int)regs.eax);
                getregs(proc, &regs);
                ptrace(PTRACE_CONT, proc, NULL, NULL);
        }

        return 0;
}

void getregs(pid_t proc, struct user_regs_struct *regs) {
        if(ptrace(PTRACE_GETREGS, proc, NULL, &regs) == -1) {
                perror("GETREGS");
                exit(1);
        }

        printf("eax: %08x\n", (unsigned int)regs->eax);
}

When I run this I get

~$ ./tracer 
eax: 0000002f 
GETREGS: No such process

I don't get why getregs() returns that error. It's almost like it is outside scope of something?

Also, something a little unrelated: EAX is always set to 0000002f no matter what process I try to execl(). Is this natural? I don't know if i'm forking the child process properly or not. Would I need to make a new question on SO for this?


Solution

  • You hit this error because you are modifying the value of the process identifier (PID) contained in the variable proc by passing its address to the wait(2) syscall.

    The wait syscall will change the value of proc with the return status of your child process upon its termination. So when you reference your child process in ptrace using proc, its value will likely be invalid and referencing no existing processes.

    And as @lornix noticed, make sure that you pass the right pointer to ptrace in the getregs function.