【问题标题】:BPF verifier rejects when try to access __sk_buff memberBPF 验证器在尝试访问 __sk_buff 成员时拒绝
【发布时间】:2021-07-27 20:42:25
【问题描述】:

我正在尝试编写一个示例 eBPF 程序,它可以访问 __sk_buff 成员并将其转储到 /sys/kernel/debug/tracing/trace.

#include <uapi/linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

SEC("dump_skb_member")
int test_prog(struct __sk_buff *skb)
{
    char fmt[] = "packet: local %u remote %u\n";
    __u32 local_ip4 = bpf_htonl(skb->local_ip4);
    __u32 remote_ip4 = bpf_htonl(skb->remote_ip4);
    bpf_trace_printk(fmt, sizeof(fmt), local_ip4, remote_ip4);

    return BPF_OK;
}


char _license[] SEC("license") = "GPL";

当我编译这段代码并加载这个程序时

ip route add 192.168.56.104 encap bpf out obj sample.o section dump_skb_member dev enp0s8

抛出一个错误。

Prog section 'dump_skb_member' rejected: Permission denied (13)!
 - Type:         11
 - Instructions: 21 (0 over limit)
 - License:      GPL

Verifier analysis:

0: (b7) r2 = 685349
1: (63) *(u32 *)(r10 -8) = r2
2: (18) r2 = 0x2065746f6d657220
4: (7b) *(u64 *)(r10 -16) = r2
5: (18) r2 = 0x7525206c61636f6c
7: (7b) *(u64 *)(r10 -24) = r2
8: (18) r2 = 0x203a74656b636170
10: (7b) *(u64 *)(r10 -32) = r2
11: (61) r4 = *(u32 *)(r1 +92)
invalid bpf_context access off=92 size=4
processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

Error fetching program/map!

但如果我不调用 bpf_trace_printk 转储成员,它可以加载。

我的问题是为什么错误是调用 bpf_trace_printk 引起的?

【问题讨论】:

    标签: bpf ebpf


    【解决方案1】:

    该错误不是bpf_trace_prink()引起的,而是由仅在您调用bpf_trace_printk()时出现在您的字节码中的skb访问引起的。

    您使用的BPF_PROG_TYPE_LWT_OUT 类型的程序不允许访问skb-&gt;local_ip4skb-&gt;remote_ip4

    查看内核代码:此类型的 function that checks for valid access 对于 skb 中的某些偏移或范围返回 false:

    case bpf_ctx_range_till(struct __sk_buff, family, local_port):
    [...]
            return false;
    

    这对应于local_ip4remote_ip4are defined的范围:

    struct __sk_buff {
        [...]
    
        /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */
        __u32 family;
        __u32 remote_ip4;   /* Stored in network byte order */
        __u32 local_ip4;    /* Stored in network byte order */
        __u32 remote_ip6[4];    /* Stored in network byte order */
        __u32 local_ip6[4]; /* Stored in network byte order */
        __u32 remote_port;  /* Stored in network byte order */
        __u32 local_port;   /* stored in host byte order */
        /* ... here. */
    

    当您删除对 bpf_trace_printk() 帮助程序的调用时,不再需要您的局部变量,并且 clang 会将您的代码编译出程序。读取禁止偏移的尝试不再是字节码的一部分,因此程序加载成功。

    【讨论】:

      猜你喜欢
      • 2020-08-25
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 2019-12-12
      • 2014-11-09
      相关资源
      最近更新 更多