使用ptrace调试时进程查找失败的原因及权限疑问
ptrace调试问题排查与权限疑问解答
问题描述
- 使用ptrace调试时,父进程(tracer)启动子进程(tracee)后,通过
PTRACE_SINGLESTEP单步跟踪指令,出现部分调用提示“进程未找到”错误,最终所有调用失败,需排查原因。 - 确认:若父进程属主/组为X,子进程属主/组为Y,父进程跟踪子进程时,子进程权限是否会被修改为X?
相关代码与环境
父进程代码
#include <stdio.h> #include <errno.h> #include <string.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <sys/syscall.h> #include <sys/user.h> #include <sys/reg.h> int debug_process() { setvbuf(stdout, 0, 2, 0); pid_t pid; long orig_eax; int status; struct user_regs_struct regs; unsigned int *addr = 0x0804a024; int i = 0; pid = fork(); if(pid == 0) { if (execve("child.o", NULL, NULL) == -1) printf("%s", "Could not execve\n"); return 0; } else { sleep(2); kill(pid, SIGINT); while(1) { int output = ptrace(PTRACE_PEEKDATA, pid, (void *)addr, 0); if (output == -1) perror(NULL); printf("output: %d\n", output); output = ptrace(PTRACE_GETREGS, pid, NULL, ®s); if (output == -1) perror(NULL); printf("output: %d\n", output); printf("%X called with eip: %X ebx: %X, ecx: %X, edx: %X\n", regs.eax, regs.eip, regs.ebx, regs.ecx, regs.edx); getchar(); output = ptrace(PTRACE_SINGLESTEP, pid, 0, 0); if (output == -1) perror(NULL); printf("output: %d\n", output); printf("%s", "-----------------------------------------\n"); } } return 0; } int main() { debug_process(); }
子进程代码
#include <stdio.h> #include <errno.h> #include <string.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <sys/syscall.h> #include <sys/user.h> #include <sys/reg.h> int i = 143; int main() { setvbuf(stdout, 0, 2, 0); ptrace(PTRACE_TRACEME, 0, 0, 0); printf("child4 starts...\n"); while(i != 245) { printf("hello from child\n"); } printf("child4 outside loop...\n"); }
编译命令与内核版本
- 编译命令:
gcc -m32 parent.c -o parent.o; gcc -m32 child.c -o child.o - 内核版本:4.4.179-0404179-generic
运行输出
... hello from childNo such process output: -1 output: 0 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 FFFFFE00 called with eip: F779FB59 ebx: 1, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- output: 143 output: 0 1 called with eip: F763E0C4 ebx: F7788D60, ecx: F7788DA7, edx: 1 output: 0 ----------------------------------------- No such process output: -1 No such process output: -1 1 called with eip: F763E0C4 ebx: F7788D60, ecx: F7788DA7, edx: 1 ...
问题解答
1. “进程未找到”错误原因
代码存在两个核心问题导致ptrace操作失败:
- 跟踪流程错误:子进程调用
PTRACE_TRACEME后,会在执行下一个系统调用时暂停并通知父进程,但父进程未调用wait()等待子进程进入暂停状态,而是用sleep(2)+kill(pid, SIGINT)触发跟踪,这会导致父进程在子进程未处于被跟踪暂停状态时发起ptrace操作,此时子进程可能仍在运行,ptrace无法正常操作,从而报错“进程未找到”。 - 循环中未等待子进程状态更新:每次调用
PTRACE_SINGLESTEP后,子进程执行一步指令会再次暂停,父进程必须调用wait()获取子进程的状态变化,确认子进程已暂停后,才能继续执行后续的PTRACE_PEEKDATA、PTRACE_GETREGS等操作。循环中缺少wait()步骤,导致后续ptrace操作时子进程可能处于运行状态,操作失败。
修正方案:
- 父进程在fork后,立即调用
wait(&status)等待子进程因PTRACE_TRACEME触发的暂停,替换sleep和kill逻辑; - 每次调用
PTRACE_SINGLESTEP后,必须调用wait(&status)等待子进程暂停,再执行后续ptrace操作。
2. 子进程权限是否会被修改
不会。ptrace跟踪操作不会修改子进程的属主/组:
- 若子进程通过fork+execve启动,且execve的程序属主/组为Y,则子进程的属主/组就是Y,跟踪过程中不会被修改为父进程的X;
- ptrace仅要求父进程具备跟踪权限(如root用户、父进程与子进程属主相同,或系统配置允许跨用户跟踪),但不会改变子进程的uid/gid属性。
内容的提问来源于stack exchange,提问作者nadav levin
相关产品推荐
相关产品推荐

