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

eBPF获取套接字地址族返回异常值问题求助

解决eBPF kprobe读取套接字地址族错误的问题

你的核心问题是kprobe的函数参数定义完全错误,导致你读取的内存地址根本不是struct sock的实例,自然会得到随机的垃圾值。

问题根源

内核中sock_recvmsg的实际函数签名并非直接接收struct sock *,而是:

int sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags);

你把kprobe的入口函数参数定义成struct sock *sk,相当于把第一个参数struct kiocb *iocb的地址当成了sock指针,读取的内存完全不对,所以得到的skc_family是随机值。

修正方案

需要从正确的参数位置获取struct socket *,再通过socket->sk拿到struct sock实例,之后再读取地址族:

#include <linux/socket.h>
#include <linux/net.h>

#define AF_INET    2
#define AF_INET6   10

SEC("kprobe/sock_recvmsg")
int kprobe_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags)
{
    if (!sock || !sock->sk) {
        return 0;
    }

    u16 family;
    // 用bpf_core_read更安全,适配内核结构体偏移变化
    bpf_core_read(&family, sizeof(family), &sock->sk->__sk_common.skc_family);
    bpf_printk("kprobe/sock_recvmsg family: %d", family);

    if (family == AF_INET || family == AF_INET6) {
        u32 tid = bpf_get_current_pid_tgid() >> 32;
        bpf_printk("kprobe/sock_recvmsg tid: %d", tid);
        u32 value = 1;
        bpf_map_update_elem(&inetsocket, &tid, &value, BPF_ANY);
    }

    return 0;
}

额外注意事项

  • 如果你的内核版本较旧,bpf_core_read不可用,可以用bpf_probe_read_kernel替代,但bpf_core_read能自动处理内核结构体的偏移变化,兼容性更好。
  • 必须添加空指针检查(!sock || !sock->sk),避免访问无效内存导致程序崩溃或被内核拒绝加载。
  • 同样的问题也会出现在sock_sendmsg的kprobe中,需要同步修正参数定义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:35:35