You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置PTRACE_O_TRACEFORK后ptrace仍无法追踪fork子进程

解决ptrace无法追踪fork/clone子进程的问题

以下是你代码可能存在的几个关键问题及对应修复方案:

1. 仅维护单个追踪PID,丢失原进程追踪

你提到通过wait更新child变量,但fork后原父进程和新子进程都处于需被追踪的状态,只保留一个PID会导致原进程的后续系统调用被忽略。必须用集合(比如数组、链表)保存所有需要追踪的进程ID,每次处理完一个进程的事件后,继续监听所有进程的状态变化。

2. 未正确处理fork/clone事件以获取子进程PID

当设置PTRACE_O_TRACEFORK/PTRACE_O_TRACECLONE后,被追踪进程执行fork/clone时,你会收到带PTRACE_EVENT_FORK/PTRACE_EVENT_CLONE标识的SIGTRAP。此时需要:

  • 调用PTRACE_GETEVENTMSG获取新生成的子进程PID
  • 对新PID执行PTRACE_SYSCALL(或PTRACE_CONT),同时为它设置相同的追踪选项(比如PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE),确保它后续的fork/clone操作也能被追踪

3. waitpid调用参数错误

必须使用waitpid(-1, &status, __WALL | WUNTRACED)来监听所有被追踪进程的状态变化,而非仅监听最初的child PID。其中-1表示等待任意子进程,__WALL包含对clone生成进程的监听,WUNTRACED确保捕获进程暂停的状态。

修复后的tracer.c关键代码示例

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

#define MAX_PROCS 100
pid_t tracked_procs[MAX_PROCS];
int proc_count = 0;

void add_tracked_proc(pid_t pid) {
    if (proc_count < MAX_PROCS) {
        tracked_procs[proc_count++] = pid;
    }
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <program> [args]\n", argv[0]);
        exit(1);
    }

    pid_t child = fork();
    if (child == 0) {
        // 子进程:启动被追踪程序
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execvp(argv[1], &argv[1]);
        perror("execvp failed");
        exit(1);
    } else {
        add_tracked_proc(child);
        int status;
        waitpid(child, &status, WUNTRACED);
        // 设置初始追踪选项
        ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE | PTRACE_O_EXITKILL);

        while (proc_count > 0) {
            // 等待任意被追踪进程的状态变化
            pid_t pid = waitpid(-1, &status, __WALL | WUNTRACED);
            if (pid == -1) {
                perror("waitpid failed");
                break;
            }

            if (WIFEXITED(status)) {
                // 进程退出,从追踪列表移除
                for (int i = 0; i < proc_count; i++) {
                    if (tracked_procs[i] == pid) {
                        tracked_procs[i] = tracked_procs[--proc_count];
                        break;
                    }
                }
                continue;
            }

            if (WIFSTOPPED(status)) {
                int sig = WSTOPSIG(status);
                if ((sig == SIGTRAP) && (status >> 16) != 0) {
                    // 处理追踪事件
                    int event = status >> 16;
                    if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_CLONE) {
                        pid_t new_pid;
                        ptrace(PTRACE_GETEVENTMSG, pid, NULL, &new_pid);
                        printf("New process created: %d\n", new_pid);
                        // 对新进程设置追踪选项并继续执行
                        ptrace(PTRACE_SETOPTIONS, new_pid, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE | PTRACE_O_EXITKILL);
                        ptrace(PTRACE_SYSCALL, new_pid, NULL, NULL);
                        add_tracked_proc(new_pid);
                    }
                }
                // 继续当前进程的系统调用追踪
                ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
            }
        }
    }
    return 0;
}

额外注意事项

  • 确保被追踪程序(random.c)中的fork/clone调用未被其他手段拦截或修改
  • 运行tracer需要足够权限(比如root,或临时设置ptrace_scope为0:echo 0 > /proc/sys/kernel/yama/ptrace_scope)

内容的提问来源于stack exchange,提问作者frazz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:47:34