Re: XDP invalid memory access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Vincent Li <mchun.li@xxxxxxxxx> writes:

> On Thu, 16 Jan 2020, Toke Høiland-Jørgensen wrote:
>
> Hi Toke,
>
>> 
>> You could also try the xdp-loader in xdp-tools:
>> https://github.com/xdp-project/xdp-tools
>> 
>> It's somewhat basic still, but should be able to at least load a basic
>> program - please file a bug report if it fails.
>
> I tried the xdp-tools xdp-loader, when the optlen is global variable, I 
> got:
> # xdp-loader load enp3s0 tcp_option.o
> Couldn't load BPF program: Relocation failed
>
> if I move the optlen, i variable to local variable, I got:
>
> # xdp-loader load enp3s0 tcp_option.o
> Couldn't load eBPF object: Invalid argument(-22)

OK, I tried this, and there were a couple of issues:

- The xdp-loader didn't set the BPF program type to XDP, and since your
  section name doesn't have an xdp_ prefix libbpf couldn't auto-detect
  it. I've pushed a fix for this to the xdp-tools repo so the loader
  will always set the program type to XDP now.

- There are a couple of bugs in your program:

First, when compiling with warnings turned on, I get this:

tcp_options.c:64:29: error: variable 'op' is uninitialized when used here [-Werror,-Wuninitialized]
                        if (op[i] == TCPOPT_EOL ) {
                            ^~
tcp_options.c:43:23: note: initialize the variable 'op' to silence this warning
        const __u8 *op;
                      ^
                       = 0

after fixing that (adding this line after the optlen = assignment):

                op = (const __u8 *)(tcphdr + 1);

the verifier then complains about out-of-bounds reading of the packet
data (pass -vv to xdp-loader to get the full debug output from libbpf).
You are not checking that the op pointer doesn't read out-of-bounds.

I fixed that by adding a couple of bounds checks inside the for loop.
The whole thing now looks like this:

                optlen = tcphdr->doff*4 - sizeof(*tcphdr);
                op = (const __u8 *)(tcphdr + 1);
                for (i = 0; i < optlen; ) {
                        if ((void *)op + i + 1 > data_end)
                                return 0;
                        if (op[i] == TCPOPT_EOL ) {
                                char fmt[] = "XDP: tcp source : %d tcp option eol\n";
                                bpf_trace_printk(fmt, sizeof(fmt), (int)tcphdr->source);
                                return 1;
                        }
                        if (op[i] < 2)
                                i++;
                        else
                                i += ((void *)op + 2 < data_end && op[i+1]) ? : 1;
                }


With this, I can successfully load the program using xdp-loader. Turning
the variables back into globals still doesn't work, but I think that
error message should be fairly obvious:

libbpf: invalid relo for 'op' in special section 0xfff2; forgot to initialize global var?..

-Toke





[Index of Archives]     [Linux Networking Development]     [Fedora Linux Users]     [Linux SCTP]     [DCCP]     [Gimp]     [Yosemite Campsites]

  Powered by Linux