Home > front end >  PTRACE_GET_SYSCALL_INFO always returns info.op as "PTRACE_SYSCALL_INFO_NONE"
PTRACE_GET_SYSCALL_INFO always returns info.op as "PTRACE_SYSCALL_INFO_NONE"

Time:05-28

Basically the title, i can't get it to work, nor can i find any reason why it shouldn't work.

ptrace(2)'s manual states that Linux 5.3 is required and i am running Linux 5.17.4, the following simplified code compiles without any warnings, runs without any errors while detecting every single system call and yet syscall_info.op always has value PTRACE_SYSCALL_INFO_NONE.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <sys/user.h>

#include <syscall.h>
#include <sys/ptrace.h>
#include <linux/ptrace.h>

#include <sys/errno.h>

int main(int argc, char **argv) {
    pid_t pid = fork();

    switch(pid) {
        case -1:
            //error...
        case 0:
            ptrace(PTRACE_TRACEME, 0, NULL, NULL);
            execvp(argv[1], argv   1);
            //error...
    }

    waitpid(pid, NULL, 0);
    ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_EXITKILL);

    struct ptrace_syscall_info syscall_info;
    size_t size = sizeof(syscall_info);
    while(1) {
        if(ptrace(PTRACE_SYSCALL, pid, NULL, NULL) == -1) {
            //error...
        }
        if(waitpid(pid, NULL, 0) == -1) {
            //error...
        }
        
        // syscall entry
        if(ptrace(PTRACE_GET_SYSCALL_INFO, pid, (void *)size, &syscall_info) == -1) {
            //error...
        }

        /* syscall_info.op is always PTRACE_SYSCALL_INFO_NONE
           instead of PTRACE_SYSCALL_INFO_ENTRY */

        if(ptrace(PTRACE_SYSCALL, pid, NULL, NULL) == -1) {
            //error...
        }
        if(waitpid(pid, NULL, 0) == -1) {
            //error...
        }

        // syscall exit
        if(ptrace(PTRACE_GET_SYSCALL_INFO, pid, (void *)size, &syscall_info) == -1) {
            if(errno == ESRCH) {
                exit(syscall_info.exit.rval);
            }
            //error...
        }

        /* Same here, should be PTRACE_SYSCALL_INFO_EXIT but still
           is PTRACE_SYSCALL_INFO_NONE */
    }
}

Have been googling for the past 3 days and i wasn't able to find much to validate if i am using it correctly or any posts explaining why this shouldn't work. I went as far as to study strace's source to see how they do it and all i could find was a couple of macros testing whether PTRACE_GET_SYSCALL_INFO is supported in the first place but no idea as to what those tests were. If there are certain criteria for PTRACE_GET_SYSCALL_INFO other than kernel version why aren't they listed in the manual?

CodePudding user response:

After some digging, it appears that you have to enable the PTRACE_O_TRACESYSGOOD option of PTRACE_SETOPTIONS in order to get full info from PTRACE_GET_SYSCALL_INFO.

This requirement doesn't seem to be documented. It's unclear if it is intended or if it's a kernel bug.

  • Related