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

使用ptrace调试时进程查找失败的原因及权限疑问

ptrace调试问题排查与权限疑问解答

问题描述

  1. 使用ptrace调试时,父进程(tracer)启动子进程(tracee)后,通过PTRACE_SINGLESTEP单步跟踪指令,出现部分调用提示“进程未找到”错误,最终所有调用失败,需排查原因。
  2. 确认:若父进程属主/组为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, &regs);
            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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:45:21