Bcc: eBPF verifier (Ubuntu 17.04, Kernel 4.14RC4) error for SOCKET_FILTER

Created on 2 Nov 2017  路  7Comments  路  Source: iovisor/bcc

Hello iovisor,

I am writing a simple SOCKET_FILTER in eBPF for measuring purposes. Therefore I want to extract the UDP payload of a packet.
However, the verifier will not let me do it, my code currently looks like this:

SEC("socket1")
int sockfmdel(struct __sk_buff *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    struct iphdr *iph = data;
    struct udphdr *udp = data + sizeof(*iph);

    if (data + sizeof(*iph) + sizeof(*udp) > data_end)
        return 0;

... and for the if-branch I am already not allowed to check the condition. getting the following error:

bpf_load_program(prog_cnt=0) err=13
0: (b7) r0 = 0
1: (61) r2 = *(u32 *)(r1 +80)
invalid bpf_context access off=80 size=4

Why is the verifier complaining here? In XDP programs this kind of checking works. My understanding is that, if I want to access the UDP header data I need to check that they are within the change of data to data_end.
But how can I guarantee this if even the checking of this condition is forbidden? Is this something special to SOCKET_FILTER programs?

Any help would be highly appreciated since I already spent 10 hours yesterday trying to solve this problem.

Kind regards
Jan

All 7 comments

You cannot directly access the packet data for the sk_buff mirror (__sk_buff), you need to use load_word/byte/half. See the examples in samples/bpf/.

Thank you pchaigno for you answer. I thought that I had seen a developer discussion a few weeks ago where they said that the "load_byte" functions were somehow deprecated and the more simple way I described above was used. Thats why I chose this way.
But I guess that just works with XDP then.

I thought that I had seen a developer discussion a few weeks ago where they said that the "load_byte" functions were somehow deprecated and the more simple way I described above was used.

That's possible, things evolve rapidly. If you find that discussion again, I'd be curious to read it :-)

EDIT: That might also depend on your kernel version if it's a recent change.

I have searched for it again, it was here:

https://www.spinics.net/lists/netdev/msg376382.html

Indeed, they are just talking about the tc layer, though. However, I do not really understand why it is okay to have direct data access at XDP and tc level, but not at socket filter level.

I checked the verifier to make sure. Accesses to data and data_end are explicitly forbidden here for sk_filter programs: http://elixir.free-electrons.com/linux/v4.14-rc7/source/net/core/filter.c#L3452.

However, I do not really understand why it is okay to have direct data access at XDP and tc level, but not at socket filter level.

I don't know. Could just be that it wasn't deemed necessary (if the primary reason for XDP and tc was the performance overhead).
You could ask on the iovisor mailing list, you'll reach a larger audience.

The SOCKET_FILTER program can execute by non-root user. They cannot directly access pkt data through "packet" pointer by design. They can use load_byte etc. to access packet data.

The SOCKET_FILTER program can execute by non-root user.

Ah! Right, completely forgot that. Thanks @yonghong-song for the clarification!

Was this page helpful?
0 / 5 - 0 ratings