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

如何通过Rust结合ptrace追踪Docker容器内系统调用?

容器内进程系统调用追踪方案(Rust + ptrace)

一、主机端定位容器内进程的全局PID

Docker容器基于PID Namespace实现进程隔离,容器内的PID是独立于主机的,要追踪必须先找到进程对应的主机全局PID,方法如下:

  1. 获取容器init进程的主机PID(容器内PID=1对应的主机PID):
    docker inspect -f '{{.State.Pid}}' <container-id>
    
  2. 进入容器的PID Namespace查看内部进程列表:
    sudo nsenter -t <容器init的主机PID> -p ps aux
    
  3. 匹配容器内PID到主机全局PID:
    找到目标进程的容器内PID后,在主机上执行:
    sudo grep -l '<容器内PID>' /proc/*/status
    
    输出路径中的数字即为该进程的主机全局PID(例如/proc/1234/status中的1234)

二、解决PID不符问题

你当前追踪的是docker exec进程的主机PID,而非容器内测试程序的PID。修正方法:

  • 先按上述步骤找到测试程序对应的主机全局PID
  • 用ptrace直接attach到这个PID,而非docker exec的进程ID

三、捕获mkdir/rmdir系统调用的注意事项

  1. 系统调用号的实际映射:部分libc封装的函数会调用底层不同的系统调用,比如mkdir可能实际调用mkdirat(x86_64系统调用号258),可先在容器内用strace ./测试程序确认实际触发的系统调用。
  2. ptrace选项配置:必须开启TRACESYSGOOD标记,方便区分系统调用触发的信号与普通信号。
  3. 事件处理逻辑:需要分别处理SyscallEnter和SyscallExit事件,不能只监听进程启动/退出。

四、Rust + pete库实现示例

use pete::{Ptracer, TraceOptions, Event};
use nix::sys::ptrace;
use nix::unistd::Pid;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 替换为目标进程的主机全局PID
    let target_pid = Pid::from_raw(1234);

    let mut tracer = Ptracer::new();
    // 开启系统调用追踪标记,便于区分信号类型
    tracer.set_options(TraceOptions::TRACESYSGOOD)?;
    // 附加到目标进程
    tracer.attach(target_pid)?;

    loop {
        match tracer.wait()? {
            // 捕获系统调用进入事件
            Event::SyscallEnter(pid, regs) => {
                let syscall_num = regs.rax as i32;
                // x86_64系统调用号:mkdir=83, rmdir=84, mkdirat=258
                match syscall_num {
                    83 => println!("[PID {}] 进入mkdir调用", pid),
                    84 => println!("[PID {}] 进入rmdir调用", pid),
                    258 => println!("[PID {}] 进入mkdirat调用", pid),
                    _ => {}
                }
                // 继续追踪下一个系统调用
                ptrace::syscall(pid, None)?;
            }
            // 捕获系统调用退出事件
            Event::SyscallExit(pid, regs) => {
                let syscall_num = regs.rax as i32;
                match syscall_num {
                    83 => println!("[PID {}] mkdir调用完成,返回值: {}", pid, regs.rax),
                    84 => println!("[PID {}] rmdir调用完成,返回值: {}", pid, regs.rax),
                    258 => println!("[PID {}] mkdirat调用完成,返回值: {}", pid, regs.rax),
                    _ => {}
                }
                ptrace::syscall(pid, None)?;
            }
            // 进程退出时终止追踪
            Event::Exit(pid, status) => {
                println!("[PID {}] 进程退出,状态码: {}", pid, status);
                break;
            }
            // 其他事件(如进程暂停),继续执行
            _ => ptrace::cont(target_pid, None)?,
        }
    }

    Ok(())
}

五、运行注意事项

  • 必须以root权限运行程序(或给程序添加CAP_SYS_PTRACE权限),否则无法attach到目标进程:
    sudo ./target/debug/your-program
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:54:51