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

如何在eBPF程序中从pt_regs读取socket->sk并通过验证器

解决eBPF kprobe读取newsock->sk的权限拒绝问题

问题核心

你遇到的R6 invalid mem access 'inv'错误,是eBPF验证器对内核内存访问的安全限制导致的:直接解引用内核指针的多层访问(比如newsock->sk)会被验证器判定为非法,即使你用bpf_probe_read_kernel读取单个字段成功,多层指针访问仍需严格遵循安全规则。

读取newsock->sk的正确方法

1. 用嵌套的bpf_probe_read_kernel读取

struct socket中的sk是二级指针,不能直接访问,必须通过bpf_probe_read_kernel先将sk指针读取到局部变量,再操作该变量。示例代码如下:

// 仅定义需要的字段,偏移需匹配目标内核版本
struct socket {
    struct sock *sk;
};

struct sock {
    // 根据需求定义需要的字段,比如连接状态
    int sk_state;
};

SEC("kprobe/inet_accept")
int BPF_KPROBE(inet_accept, struct socket *sock, struct socket *newsock, int flags)
{
    struct sock *sk;
    // 先读取newsock->sk到局部变量sk
    if (bpf_probe_read_kernel(&sk, sizeof(sk), &newsock->sk) != 0) {
        return 0;
    }

    // 读取sk的字段,比如连接状态
    int sk_state;
    if (bpf_probe_read_kernel(&sk_state, sizeof(sk_state), &sk->sk_state) != 0) {
        return 0;
    }

    // 后续处理逻辑
    return 0;
}

2. 确认内核结构体偏移的正确性

不同内核版本中struct socket的字段偏移可能不同,你可以通过以下命令查看目标内核的结构体定义:

bpftool btf dump file /sys/kernel/btf/vmlinux format c | grep -A 30 "struct socket"

确保代码中sk字段的偏移与内核实际定义一致,偏移错误会直接触发验证器的非法访问报错。

3. 增加指针有效性检查

在读取sk之前,先通过读取newsock的其他字段(比如type)验证newsock指针的合法性,只有读取成功后再继续操作sk,验证器会认可这种安全的访问流程。

通过eBPF验证器的关键规则

  • 必须使用安全读取函数:所有内核内存访问都要通过bpf_probe_read_kernel(内核空间)或bpf_probe_read_user(用户空间),禁止直接解引用内核指针。
  • 避免多层直接解引用:二级及以上指针必须先读取到局部变量,再对局部变量进行操作。
  • 匹配内核结构体偏移:确保代码中使用的字段偏移与目标内核的BTF定义一致,可通过bpftool工具确认。
  • 添加错误检查:对bpf_probe_read_kernel的返回值进行判断,只有读取成功时才执行后续逻辑,验证器会认为这种访问是安全的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:15:33