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

如何在eBPF程序中解引用指针?hook文件删除遇编译报错求助

eBPF程序解引用filename指针编译报错的解决方法

问题描述

编写了一个hookdo_unlinkat跟踪文件删除的eBPF程序,程序其余部分运行正常,但尝试直接解引用从struct filename获取的filename指针时出现编译错误,而bpf_printk可以正常输出该指针指向的内容。

原始代码

#define __TARGET_ARCH_arm64 

#include <linux/ptrace.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

typedef struct {
        int counter;
} atomic_t;

struct filename {
        const char *name;
        const char *uptr;
        atomic_t refcnt;
        struct audit_names *aname;
        const char iname[0];
};

SEC("kprobe/do_unlinkat")
int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name)
{
    const char *filename = BPF_CORE_READ(name, name);

    // 此行导致报错
    if (filename!=NULL && *filename=='t') return 1;

    bpf_printk("Deleting this file:%s", filename);
    return 0;
}

错误信息

arg#0 reference type('FWD pt_regs') size cannot be determined: -22
0: R1=ctx() R10=fp0
; int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name) @ test_ebpf.c:30
...
R3 invalid mem access 'scalar'
processed 11 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

原因及解决方法

报错核心原因是:filename指向用户空间内存,eBPF验证器禁止直接解引用用户空间指针,必须通过内核提供的安全读取函数来访问。bpf_printk能正常工作是因为它内部已经封装了用户空间指针的安全读取逻辑。

修改代码,使用bpf_core_read_user安全读取指针指向的内容:

#define __TARGET_ARCH_arm64 

#include <linux/ptrace.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

typedef struct {
        int counter;
} atomic_t;

struct filename {
        const char *name;
        const char *uptr;
        atomic_t refcnt;
        struct audit_names *aname;
        const char iname[0];
};

SEC("kprobe/do_unlinkat")
int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name)
{
    const char *filename = BPF_CORE_READ(name, name);
    char first_char = 0;

    if (filename != NULL) {
        // 使用bpf_core_read_user安全读取用户空间的第一个字符
        bpf_core_read_user(&first_char, sizeof(first_char), filename);
        if (first_char == 't') {
            return 1;
        }
    }

    bpf_printk("Deleting this file:%s", filename);
    return 0;
}

关键说明

  • bpf_core_read_user是libbpf提供的封装函数,会自动处理指针合法性检查,避免触发eBPF验证器的内存访问错误。
  • 如果需要读取更长的字符串片段,可以扩展缓冲区大小,一次性读取更多字节,但需注意内存边界,防止越界访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:25:56