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

使用tracepoint/syscalls/sys_enter_execve获取argv时参数丢失求助

解决eBPF读取execve argv参数偶尔丢失的问题

问题原因

你当前的代码直接将用户空间的字符串指针传递给bpf_printk,但bpf_printk的%s格式要求指针指向内核空间内存。用户空间的内存可能因页置换、进程地址空间切换或权限限制,导致内核无法稳定读取到字符串内容,从而出现参数偶尔丢失的情况。

修复方案

需要先通过bpf_probe_read_user将用户空间的字符串拷贝到内核缓冲区,再打印缓冲区内容。同时优化循环逻辑,读到argv[i]为NULL时终止循环,避免无效读取。

修改后的task.c代码:

//go:build ignore

#include "common.h"
#include "bpf_helpers.h"

char _license[] SEC("license") = "GPL";

struct execve {
    __u64 unused;
    __u32 nr;
    const char *filename;
    const char *const *argv;
    const char *const *envp;
};

SEC("tracepoint/syscalls/sys_enter_execve")
int sys_enter_execve(struct execve *ctx) {
    for (int i = 0; i < 10; i++) {
        const char *arg_ptr = NULL;
        // 读取argv数组中的第i个指针
        if (bpf_probe_read_user(&arg_ptr, sizeof(arg_ptr), &ctx->argv[i]))
            break;
        if (!arg_ptr)
            break; // 遇到NULL终止符,停止循环
        
        char buf[64] = {0};
        // 将用户空间字符串拷贝到内核缓冲区
        bpf_probe_read_user(buf, sizeof(buf)-1, arg_ptr);
        bpf_printk("arg%d: %s ", i, buf);
    }
    bpf_printk("\n");
    return 0;
}

关键改动说明

  1. 内核缓冲区拷贝:新增char buf[64]作为内核本地缓冲区,先把用户空间的字符串内容拷贝到这里,再传递给bpf_printk,确保读取的是稳定的内核内存。
  2. 错误处理:检查bpf_probe_read_user的返回值,读取失败时直接终止循环,避免无效操作。
  3. 终止条件优化:当arg_ptr为NULL时(即argv数组的结束符),停止循环,减少不必要的系统开销。

这个方案也适用于kprobe/sys_execve的场景,原理完全一致——必须将用户空间数据拷贝到内核后再处理,不能直接引用用户空间指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:54:54