【问题标题】:how does ptrace catch fork's system call?ptrace 如何捕获 fork 的系统调用?
【发布时间】:2013-12-24 18:16:50
【问题描述】:

我尝试使用 ptrace 来捕获子进程系统调用 id,例如 execve(11) 或 fork(2)。

我的代码在这里。

#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;
}

在我看来,程序应该在屏幕上打印“2”(因为系统调用“fork” id 是 2),但是程序完成后我什么也没得到。 有人可以解释一下吗?

【问题讨论】:

  • 等等,所以你正在分叉,等待孩子完成完成后跟踪它,然后惊讶ptrace不显示分叉?
  • 这是我的错。代码“ptrace(PTRACE_TRACEME, 0, NULL, NULL);”应该添加。我想在“pid_t t = fork()”时捕获 fork 系统调用。执行。

标签: c++ c linux ptrace


【解决方案1】:

如果你的程序已经正常退出,那么

if (WIFEXITED(status)) break;

此语句可能导致不打印 2,因为它正在将其从循环中取出。

请参阅此声明。

【讨论】:

  • 对不起我的错。 “ptrace(PTRACE_TRACEME,0,NULL,NULL);”应该添加到程序中。当“pid_t t = fork()”执行时,wait4()函数不会阻塞父进程,然后我使用“ptrace(PTRACE_PEEKUSER, pid, 4 * ORIG_EAX, NULL);”获取系统调用。
【解决方案2】:

Op 现在可能不需要答案,但其他人可能需要,所以我就把它放在那里。

首先,if (syscall == SYS_execve) 行只有在您执行execv 系统调用时才有效。这意味着它将打印分配给 execv 的系统调用号,在我的机器 (x86) 中是编号 11。但是你从来没有真正调用过 execv 所以什么都不会被打印出来。

其次,您可能不会在屏幕上看到2 打印的原因是,如果您使用的是2.3.3 或更高版本,那么fork() 调用实际上并不是系统调用。 不是调用kernel's fork(),而是调用glibc fork() 包装函数,这实际上不是系统调用。

然后,此函数将调用clone() 系统调用。因此,您需要搜索克隆系统调用 ID(取决于您使用的版本)或使用 SYS_clone,如果您想捕获并操作它。

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

【讨论】:

    猜你喜欢
    • 2017-01-03
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 2012-10-23
    • 2011-06-09
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    相关资源
    最近更新 更多