user3550166
user3550166

Reputation: 129

ebpf verifier fails for accessing SK_BUFF from kprobe function

I couldn't access sk_buff from kprobe function. when i load and run this program, ebpf verifier fails with this. Do anyone know what im doing wrong here?

Error:

2022/04/20 20:56:17 loading objects: field NfHookSlow: program nf_hook_slow: load program: permission denied: ; int BPF_KPROBE(nf_hook_slow, struct sk_buff *skb, struct nf_hook_state *state,
0: (79) r1 = *(u64 *)(r1 +112)
; if (skb)
1: (15) if r1 == 0x0 goto pc+10
 R1_w=inv(id=0) R10=fp0
; struct ethhdr *eth = (struct ethhdr *)(skb->head + skb->mac_header);
2: (69) r2 = *(u16 *)(r1 +182)
R1 invalid mem access 'inv'
processed 3 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

kprobe Program:

SEC("kprobe/nf_hook_slow")
int BPF_KPROBE(nf_hook_slow, struct sk_buff *skb, struct nf_hook_state *state,
               const struct nf_hook_entries *e, unsigned int s)
{

    if (skb)
    {
        struct ethhdr *eth = (struct ethhdr *)(skb->head + skb->mac_header);
        bpf_printk("eth: %d", eth->h_proto);
    }

    return 0;
}

I have even tried to read from kernel memory(bpf_probe_read_kernel(&proto, sizeof(proto), &eth->h_proto);) and print it but that's also failing

Error:

0: (79) r1 = *(u64 *)(r1 +112)
; if (skb)
1: (15) if r1 == 0x0 goto pc+9
 R1_w=inv(id=0) R10=fp0
; struct ethhdr *eth = (struct ethhdr *)(skb->head + skb->mac_header);
2: (69) r2 = *(u16 *)(r1 +182)
R1 invalid mem access 'inv'
processed 3 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

Program:

SEC("kprobe/nf_hook_slow")
int BPF_KPROBE(nf_hook_slow, struct sk_buff *skb, struct nf_hook_state *state,
               const struct nf_hook_entries *e, unsigned int s)
{
  if (skb)
  {
    struct ethhdr *eth = (struct ethhdr *)(skb->head + skb->mac_header);
    u16 proto;
    bpf_probe_read_kernel(&proto, sizeof(proto), &eth->h_proto);
  }
  return 0;
}

Upvotes: 1

Views: 495

Answers (1)

user3550166
user3550166

Reputation: 129

I fixed it. Looks like have to use bpf_probe_read to read any memeber in sk_buff.

#define member_address(source_struct, source_member)                                                 \
    ({                                                                                               \
        void *__ret;                                                                                 \
        __ret = (void *)(((char *)source_struct) + offsetof(typeof(*source_struct), source_member)); \
        __ret;                                                                                       \
    })
#define member_read(destination, source_struct, source_member) \
    do                                                         \
    {                                                          \
        bpf_probe_read(                                        \
            destination,                                       \
            sizeof(source_struct->source_member),              \
            member_address(source_struct, source_member));     \
    } while (0)

SEC("kprobe/nf_hook_slow")
int BPF_KPROBE(nf_hook_slow, struct sk_buff *skb, struct nf_hook_state *state)
{
    char *head;
    __u16 mac_header, nw_header, tcp_header, eth_proto;

    if (skb)
    {
        member_read(&head, skb, head);
        member_read(&mac_header, skb, mac_header);
        member_read(&nw_header, skb, network_header);

        char *eth_head = head + mac_header;
        bpf_probe_read(&eth_proto, sizeof(u16), &eth_head[12]);
    }

 }

Upvotes: 0

Related Questions