0

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 Answers1

0

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.

NetOptimizer
  • 71
  • 1
  • 5
  • I've edited my question to include code I had omitted before. Doesn't look like adding more validation is helping here. Validator is looking for max TCP header size of 60 to be accessible. – user2126078 Mar 21 '22 at 14:24
  • Found an example at https://lwn.net/Articles/887722/ . In this patch, they are extending the packet to the maximum TCP header size calling bpf_xdp_adjust_tail() and then bpf_csum_diff() is called. That seems to work! – user2126078 Mar 22 '22 at 03:58