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

eBPF程序附加tracepoint时触发空指针异常问题排查

问题描述

我编写的eBPF程序无法附加到tracepoint syscalls/sys_exit_mmap,调用ebpf.NewCollectionWithOptions()时抛出错误:

invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x6ab850]

排查后确认,问题出在e->sys_exit_mmap_ret = (__s32)ctx->ret这行代码——如果将其替换为直接赋值0(不使用ctx),错误就会消失。相关源码片段如下:

struct rb_event {
        __u16 opcode;
        union {
                // ...
                struct {
                        __s32 sys_exit_mmap_ret;
                };
        };
};

// see /sys/kernel/debug/tracing/events/syscalls/sys_exit_mmap/format
struct sys_exit_mmap_ctx {
        __s64 ret;
};

SEC("tracepoint/syscalls/sys_exit_mmap")
int sys_exit_mmap(
        struct sys_exit_mmap_ctx *ctx
) {
        struct rb_event *e;
        e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
        if (e == NULL) {
                return 0;
        }

        e->opcode = OPCODE_SYS_EXIT_MMAP;
        e->sys_exit_mmap_ret = (__s32)ctx->ret;

        bpf_ringbuf_submit(e, 0);
        return 0;
}
问题根源与修复方案

问题核心是你自定义的struct sys_exit_mmap_ctx和内核实际的tracepoint上下文结构不匹配。

Linux tracepoint的上下文结构并非只有ret字段,它有固定的通用前置元数据结构。以sys_exit_mmap为例,内核实际的上下文结构开头是struct trace_entry(包含时间戳、PID等通用信息),之后才是ret字段。你的结构体直接定义__s64 ret,跳过了前置元数据,导致访问ctx->ret时实际访问的是内核内存中错误的地址,触发段错误。

修复步骤:

  1. 获取正确的结构体定义:执行以下命令查看sys_exit_mmap的完整tracepoint结构:
    cat /sys/kernel/debug/tracing/events/syscalls/sys_exit_mmap/format
    
    或者用bpftool从BTF中导出更准确的C结构体:
    bpftool btf dump file /sys/kernel/btf/vmlinux format c | grep -A 25 "struct trace_event_raw_sys_exit"
    
  2. 替换自定义结构体:将上述命令得到的完整结构体复制到你的eBPF代码中,替换现有的struct sys_exit_mmap_ctx。
  3. 正确访问ret字段:在新的结构体中,ret字段位于通用元数据之后,确保代码中访问的是正确的字段位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:43:40