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

eBPF fentry/fexit读取pt_regs参数报invalid bpf_context access错误

fentry/fexit 系统调用追踪触发 invalid bpf_context access 问题说明

问题现象

基于fentry/fexit实现eBPF系统调用追踪时,部分环境下读取struct pt_regs *regs参数会触发程序加载报错,复现代码如下:

SEC("fentry/__x64_sys_recvfrom")
int BPF_PROG(fentry_syscall, struct pt_regs *regs) {
  struct event t;

  bpf_get_current_comm(t.comm, TASK_COMM_LEN);

  u64 id = bpf_get_current_pid_tgid();
  t.pid = id >> 32;

  // 部分环境下该行触发错误
  t.fd = PT_REGS_PARM1_CORE(regs);

  bpf_printk("comm: %s, pid: %d, fd: %d", t.comm, t.pid, t.fd);

  return 0;
}

程序加载时的报错信息:

$ sudo ./output
2022/07/01 03:33:01 loading objects: field FentrySyscall: program fentry_syscall: load program: permission denied:
        arg#0 type is not a struct
        Unrecognized arg#0 type PTR
        ; int BPF_PROG(fentry_syscall, struct pt_regs *regs) {
        0: (79) r6 = *(u64 *)(r1 +0)
        func '__x64_sys_recvfrom' arg0 type FWD is not a struct
        invalid bpf_context access off=0 size=8
        processed 1 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

排查结论

该错误仅出现在/sys/kernel/btf/vmlinux中对应系统调用的参数被声明为FWD(前向声明)类型的场景:

  • 异常环境下BTF信息中,pt_regs仅存在前向声明,无具体结构体布局定义:
$ bpftool btf dump file /sys/kernel/btf/vmlinux format raw
...
[13362] FWD 'pt_regs' fwd_kind=struct
[13363] CONST '(anon)' type_id=13362
[13364] PTR '(anon)' type_id=13363
[13365] FUNC_PROTO '(anon)' ret_type_id=36 vlen=1
        '__unused' type_id=13364
...
[13608] FUNC '__x64_sys_recvmsg' type_id=13365 linkage=static
...
  • 正常运行环境下BTF信息中,pt_regs存在完整的结构体类型定义:
$ bpftool btf dump file /sys/kernel/btf/vmlinux format raw
[1] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
...
[226] STRUCT 'pt_regs' size=168 vlen=21
        'r15' type_id=1 bits_offset=0
        'r14' type_id=1 bits_offset=64
        'r13' type_id=1 bits_offset=128
        'r12' type_id=1 bits_offset=192
        'bp' type_id=1 bits_offset=256
        'bx' type_id=1 bits_offset=320
        'r11' type_id=1 bits_offset=384
        'r10' type_id=1 bits_offset=448
        'r9' type_id=1 bits_offset=512
        'r8' type_id=1 bits_offset=576
        'ax' type_id=1 bits_offset=640
        'cx' type_id=1 bits_offset=704
        'dx' type_id=1 bits_offset=768
        'si' type_id=1 bits_offset=832
        'di' type_id=1 bits_offset=896
        'orig_ax' type_id=1 bits_offset=960
        'ip' type_id=1 bits_offset=1024
        'cs' type_id=1 bits_offset=1088
        'flags' type_id=1 bits_offset=1152
        'sp' type_id=1 bits_offset=1216
        'ss' type_id=1 bits_offset=1280
...
[5183] CONST '(anon)' type_id=226
...
[5189] PTR '(anon)' type_id=5183
...
[5321] FUNC_PROTO '(anon)' ret_type_id=42 vlen=1
        '__unused' type_id=5189
...
[17648] FUNC '__x64_sys_recvmsg' type_id=5321 linkage=static
...

多发行版测试验证,pt_regs的BTF定义差异由发行版内核补丁、编译配置、系统调用所在编译单元的头文件引用情况共同决定,和内核版本、发行版、具体追踪的系统调用三个因素都相关。

根本原因

内核编译生成BTF信息时,如果某个系统调用实现所在的编译单元没有引入struct pt_regs的完整定义头文件(如asm/ptrace.h),编译器只会为该函数原型中的pt_regs*参数生成不完整的前向声明(FWD类型),不会记录结构体的大小、字段偏移等布局信息。
eBPF验证器在校验程序对上下文参数的访问时,如果发现要访问的指针指向FWD类型,无法判定访问偏移的合法性,就会直接拒绝加载,抛出invalid bpf_context access错误。

兼容规避方案

可根据场景选择以下方案实现全新版Linux环境兼容:

  • 优先使用fentry直接按系统调用原型传参,完全绕开pt_regs读取。fentry钩子本身支持直接获取被hook函数的实际参数,不需要手动从pt_regs解析,只要BPF_PROG的参数列表和对应系统调用的原型一致,libbpf的CO-RE机制会自动完成参数重定位,不受pt_regs前向声明问题影响。修改后的示例代码如下:
SEC("fentry/__x64_sys_recvfrom")
int BPF_PROG(fentry_syscall, int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen) {
  struct event t;
  bpf_get_current_comm(t.comm, TASK_COMM_LEN);
  u64 id = bpf_get_current_pid_tgid();
  t.pid = id >> 32;
  t.fd = fd; // 直接读取参数,无需通过PT_REGS宏解析pt_regs
  bpf_printk("comm: %s, pid: %d, fd: %d", t.comm, t.pid, t.fd);
  return 0;
}
  • 对兼容性要求极高的场景,可优先选择BTF tracepoint类型的sys_enter/sys_exit挂载点,这类挂载点的上下文参数由内核明确定义,不存在类型前向声明问题,跨版本、跨发行版兼容性最稳定。
  • 确实需要读取pt_regs完整结构(如读取orig_ax字段获取系统调用号)的场景,可以在eBPF代码中内置对应架构的pt_regs结构体定义,同时通过bpf_core_type_exists宏检测内核BTF中是否存在完整的pt_regs定义,自动在fentry和tracepoint实现之间切换,做双逻辑兼容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:21:51