ebpf verifier fails for bpf_csum_diff()

318 Views Asked by At

Not able to understand why the following code fails verifier. I am doing all possible validations in this test function.

{
    if (tcph + 1 > data_end)
        return XDP_DROP;

    tcp_len = tcph->doff * 4;

    if (tcp_len < sizeof(*tcph))
        return XDP_DROP;
    if ((void *)tcph + tcp_len > data_end)
        return XDP_DROP;

    value = bpf_csum_diff(0, 0, (void *)tcph, tcp_len, 0);
    if (value == 0) return XDP_DROP;

    return XDP_PASS;
}
 

Validator failure:

44: (b7) r1 = 0
45: (b7) r2 = 0
46: (b7) r5 = 0
47: (85) call bpf_csum_diff#28
last_idx 47 first_idx 43
regs=4 stack=0 before 46: (b7) r5 = 0
regs=4 stack=0 before 45: (b7) r2 = 0
invalid access to packet, off=14 size=60, R3(id=1,off=14,r=34)
R3 offset is outside of the packet

The validator wants to access 60 bytes (max TCP header size) to pass the test.

1

There are 1 best solutions below

2
On

It fails because the BPF-prog is accessing the packet data via tcph->doff before you have boundary checked if this is safe to access:

__u16 tcp_len = tcph->doff * 4;
                ^^^^^^^^^^

Perhaps you are not aware that the XDP-project bpf-examples have code like parsing_helpers.h that can be used for your convenience.