I was unble to load my compiled bpf source code in to the kernel

288 views Asked by At
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <netinet/in.h>
#include <linux/udp.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/pkt_cls.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_perf_event.h>
#include <netinet/in.h>

struct bpf_map_def SEC("maps") timestamp_map = {
    .type = BPF_MAP_TYPE_PERCPU_ARRAY,
    .key_size = sizeof(int),
    .value_size = sizeof(uint64_t),
    .max_entries = 1,
};

SEC("filter")
int icmp_timestamp(struct __sk_buff *skb) {
    void *data_end = (void *)(long)skb->data_end;
    void *data = (void *)(long)skb->data;
    struct ethhdr *eth = data;

    if (eth->h_proto == htons(ETH_P_IP)) {
       struct iphdr *ip = data + sizeof(struct ethhdr);

        if (ip->protocol == IPPROTO_ICMP) {
            uint64_t timestamp = bpf_ktime_get_ns();
            int key = 0;
            bpf_map_update_elem(&timestamp_map, &key, &timestamp, BPF_ANY);
            return XDP_PASS;    
        }

    }
    return XDP_DROP;
}

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

#Here is the bpf source code. I have compiled the above source code successfully but I was unable to load it into the kernel. The command I used to load the compiled source code was sudo bpftool prog load name_of_code.o /sys/fs/bpf/name_of_code

#And also the error i am encountering with is

libbpf: prog 'icmp_timestamp': BPF program load failed: Permission denied

libbpf: prog 'icmp_timestamp': -- BEGIN PROG LOAD LOG --
reg type unsupported for arg#0 function icmp_timestamp#26
0: R1=ctx(off=0,imm=0) R10=fp0
; void *data = (void *)(long)skb->data;
0: (61) r1 = *(u32 *)(r1 +76)
invalid bpf_context access off=76 size=4
processed 1 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
-- END PROG LOAD LOG --
libbpf: prog 'icmp_timestamp': failed to load: -13
libbpf: failed to load object 'rocode.o'

Error: failed to load object file
1

There are 1 answers

4
pchaigno On

TL;DR. Your context should be struct xdp_md *xdp instead of struct __sk_buff *skb.

Note you will also need to check that your packet is big enough to read at the offsets you want. For example:

if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) > data_end)
    return DROP;

I'd also recommend to pass the program type to bpftool:

bpftool prog load name_of_code.o /sys/fs/bpf/name_of_code type xdp

Explanation

Your program was rejected by the BPF verifier. We can know that because verifier logs are printed (the bits with the bytecode).

reg type unsupported for arg#0 function icmp_timestamp#26
0: R1=ctx(off=0,imm=0) R10=fp0
; void *data = (void *)(long)skb->data;
0: (61) r1 = *(u32 *)(r1 +76)
invalid bpf_context access off=76 size=4

Here, it's saying that the second access to the context argument (skb->data) is trying to load memory from an incorrect offset into the context memory. That's the context offset you're loading from doesn't match what the verifier expects.

Seeing the return codes you used, I'm guessing you're trying to use a program of type XDP. In that case, the context should be of type struct xdp_md.