Re: XDP invalid memory access

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

 




On Fri, 17 Jan 2020, Toke Høiland-Jørgensen wrote:

> 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);

Thank you for mentioning the warning flags to clang, I used clang -Wall 
and see the same warning

> 
> 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.

-vv is also good tip, missed it

> 
> 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;
>                 }
> 
Good to know now everytime to check the memory bound before accessing the 
next memory

> 
> 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

I cloned your updated xdp-loader and I can load the object file fine now, 
thank you for taking your time, lesson learned :)

Vincent
 

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

  Powered by Linux