lizrice / learning-ebpf

Learning eBPF, published by O'Reilly - out now! Here's where you'll find a VM config for the examples, and more
https://www.amazon.com/Learning-eBPF-Programming-Observability-Networking/dp/1098135121
Apache License 2.0
1.19k stars 255 forks source link

chapter8 - exercises1 failure #32

Closed we1ru1 closed 9 months ago

we1ru1 commented 11 months ago

I am doing the first exercise in chapter8, modifying hello.bpf.c to print different content depending on the ping request message or response message. Here is my source program:

#include "vmlinux.h"
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include "packet.h"

int ping(struct xdp_md *ctx){

    long protocol = lookup_protocol(ctx);  
    if (protocol == 1) // ICMP  
    {  
        void *data = (void *)(long)ctx->data;      

        struct icmphdr *icmp = data + sizeof(struct ethhdr) + sizeof(struct iphdr);

        if(icmp->type == 8)  //  8 for ping request
            bpf_printk("i'm a ping request packet");

        if(icmp->type == 0)  // 0 for ping response
            bpf_printk("i'm a ping response packet");
    }  

    return XDP_PASS;
}

Then I executed thesudo make command, then:


$ sudo make
clang \
    -target bpf \
    -D __BPF_TRACING__ \
        -I/usr/include/x86_64-linux-gnu \
    -Wall \
    -O2 -o hello.bpf.o -c hello.bpf.c
bpftool net detach xdp dev lo
rm -f /sys/fs/bpf/hello
bpftool prog load hello.bpf.o /sys/fs/bpf/hello
libbpf: prog 'ping': BPF program load failed: Permission denied
libbpf: prog 'ping': -- BEGIN PROG LOAD LOG --
0: R1=ctx(off=0,imm=0) R10=fp0
0: (61) r2 = *(u32 *)(r1 +4)          ; R1=ctx(off=0,imm=0) R2_w=pkt_end(off=0,imm=0)
1: (61) r1 = *(u32 *)(r1 +0)          ; R1_w=pkt(off=0,r=0,imm=0)
2: (bf) r3 = r1                       ; R1_w=pkt(off=0,r=0,imm=0) R3_w=pkt(off=0,r=0,imm=0)
3: (07) r3 += 14                      ; R3_w=pkt(off=14,r=0,imm=0)
4: (2d) if r3 > r2 goto pc+19         ; R2_w=pkt_end(off=0,imm=0) R3_w=pkt(off=14,r=14,imm=0)
5: (69) r3 = *(u16 *)(r1 +12)         ; R1_w=pkt(off=0,r=14,imm=0) R3_w=scalar(umax=65535,var_off=(0x0; 0xffff))
6: (55) if r3 != 0x8 goto pc+17       ; R3_w=8
7: (bf) r6 = r1                       ; R1_w=pkt(off=0,r=14,imm=0) R6_w=pkt(off=0,r=14,imm=0)
8: (07) r6 += 34                      ; R6=pkt(off=34,r=14,imm=0)
9: (2d) if r6 > r2 goto pc+14         ; R2=pkt_end(off=0,imm=0) R6=pkt(off=34,r=34,imm=0)
10: (71) r1 = *(u8 *)(r1 +23)         ; R1_w=scalar(umax=255,var_off=(0x0; 0xff))
11: (55) if r1 != 0x1 goto pc+12      ; R1_w=1
12: (71) r1 = *(u8 *)(r6 +0)
invalid access to packet, off=34 size=1, R6(id=0,off=34,r=34)
R6 offset is outside of the packet
processed 13 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
-- END PROG LOAD LOG --
libbpf: prog 'ping': failed to load: -13
libbpf: failed to load object 'hello.bpf.o'
Error: failed to load object file
make: *** [Makefile:13:hello] 错误 255

I want to know what went wrong and how to correct it. thanks

lizrice commented 9 months ago

Based on these lines:

invalid access to packet, off=34 size=1, R6(id=0,off=34,r=34)
R6 offset is outside of the packet

I would imagine that the verifier is objecting that you haven't checked that the packet is long enough for the ICMP header that you're trying to access. This is mentioned in chapter 8 of the book in the section "XDP Packet Parsing"