xdp-project / xdp-tutorial

XDP tutorial
2.5k stars 579 forks source link

packet03-redirecting:libbpf: Error in bpf_object__probe_name():Operation not permitted(1). Couldn't load basic 'r0 = 0' BPF program #86

Open sofardware opened 4 years ago

sofardware commented 4 years ago

[root@localhost packet03-redirecting]# make ... [root@localhost packet03-redirecting]# t exec -n left -- ./xdp_loader -d veth0 -F --progsec xdp_pass libbpf: Error in bpf_objectprobe_name():Operation not permitted(1). Couldn't load basic 'r0 = 0' BPF program. libbpf: Error in bpf_objectprobe_global_data():Operation not permitted(1). Couldn't create simple array map. libbpf: failed to create map (name: 'xdp_stats_map'): Operation not permitted(-1) libbpf: failed to load object 'xdp_prog_kern.o' ERR: loading BPF-OBJ file(xdp_prog_kern.o) (-22): Invalid argument ERR: loading file: xdp_prog_kern.o

tohojo commented 4 years ago

sofardware notifications@github.com writes:

[root@localhost packet03-redirecting]# make ... [root@localhost packet03-redirecting]# t exec -n left -- ./xdp_loader -d veth0 -F --progsec xdp_pass libbpf: Error in bpf_objectprobe_name():Operation not permitted(1). Couldn't load basic 'r0 = 0' BPF program. libbpf: Error in bpf_objectprobe_global_data():Operation not permitted(1). Couldn't create simple array map. libbpf: failed to create map (name: 'xdp_stats_map'): Operation not permitted(-1) libbpf: failed to load object 'xdp_prog_kern.o' ERR: loading BPF-OBJ file(xdp_prog_kern.o) (-22): Invalid argument ERR: loading file: xdp_prog_kern.o

Hmm, this seems like another ulimit error; I fear the raising of the limit we are currently doing is not sufficient.

Could you try the following, please:

In place of your 't exec' line, do t his:

t enter -n left ulimit -l unlimited ./xdp_loader -d veth0 -F --progsec xdp_pass

Does this work?

sofardware commented 4 years ago

Yes,it does. Thank you very much. [root@localhost packet03-redirecting]# t enter -n left [root@localhost packet03-redirecting]# ulimit -l unlimited [root@localhost packet03-redirecting]# ./xdp_loader -d veth0 -F --progsec xdp_pass Success: Loaded BPF-object(xdp_prog_kern.o) and used section(xdp_pass)

tohojo commented 4 years ago

sofardware notifications@github.com writes:

Yes,it does. Thank you very much.

Great, thanks for confirming!

sofardware commented 4 years ago

when I added memcpy(eth->h_dest, dst, ETH_ALEN); in xdp_redirect_func, and the follow commd failed. why?

[root@localhost packet03-redirecting]# ./xdp_loader -d veth0 -F --progsec xdp_pass Success: Loaded BPF-object(xdp_prog_kern.o) and used section(xdp_pass)

int xdp_redirect_func(struct xdp_md ctx) { void data_end = (void )(long)ctx->data_end; void data = (void )(long)ctx->data; struct hdr_cursor nh; struct ethhdr eth; int eth_type; int action = XDP_PASS;

    **unsigned char dst[ETH_ALEN] = {0x2e,0x7d,0xf6,0x80,0xf9,0x26};  /* Assignment 2: fill in with the MAC address of the left inner interface */**
    unsigned ifindex = 9;//6;               /* Assignment 2: fill in with the ifindex of the left interface */

    /* These keep track of the next header type and iterator pointer */
    nh.pos = data;

    /* Parse Ethernet and IP/IPv6 headers */
    eth_type = parse_ethhdr(&nh, data_end, &eth);
    if (eth_type == -1)
            goto out;

    /* Assignment 2: set a proper destination address and call the
     * bpf_redirect() with proper parameters, action = bpf_redirect(...) */
     memcpy(eth->h_dest, dst, ETH_ALEN);
    action = bpf_redirect(ifindex, 0);

out: return xdp_stats_record_action(ctx, action); }

tohojo commented 4 years ago

sofardware notifications@github.com writes:

when I added memcpy(eth->h_dest, dst, ETH_ALEN); in xdp_redirect_func, and the follow commd failed. why?

Hmm, I think maybe because the pinned file is already there? Could you try manually removing the pinned files in /sys/fs/bpf/veth0 before loading the program?

pangbit commented 4 years ago

I met the same problem. My system kernel is 5.4.2, but it working in kernel 4.18.16.

And I change the code unsigned char dst[ETH_ALEN] = {...}; to unsigned char dst[ETH_ALEN + 1] = {...}; or unsigned char dst[] = {... ,'\0'}; both working in kernel 5.4.2.

But I dont know why...

ashutoshgrewal commented 4 years ago

I ran into this exact same issue Pagbit reported.

As soon as I add the memcpy to xdp_redirect_func

unsigned char dst[ETH_ALEN] = {0x66, 0x6d, 0xc3, 0x44, 0x30, 0x9c}; memcpy(eth->h_dest, dst, ETH_ALEN);

I get this error xdp/xdp-tutorial/packet03-redirecting# t exec -n left -- ./xdp_loader -d veth0 -F --progsec xdp_pass Success: Loaded BPF-object(xdp_prog_kern.o) and used section(xdp_pass)

However, if I change the Mac addr to

unsigned char dst[ETH_ALEN+1] = {0x66, 0x6d, 0xc3, 0x44, 0x30, 0x9c, '\0'};

it starts to work

t exec -n left -- ./xdp_loader -d veth0 -F --progsec xdp_pass Success: Loaded BPF-object(xdp_prog_kern.o) and used section(xdp_pass)

Does anyone know why?

Thanks pagbit for the workaround/fix.

falcondb commented 4 years ago

I also hit this bug. From my debugging (using ftrace), the _builtinmemcpy didn't pollute the target memory without '\0'. Is there any side effect of using _builtinmemcpy ?!

Instead I just copy the MAC bytes manually

     #pragma unroll
     for (i = 0; i < ETH_ALEN; i++) {
        eth->h_dest[i] = dest[i];
     }
andreev-io commented 3 years ago

Hitting the same problem as described above in assignment packet02-03:

libbpf: failed to pin map: Operation not permitted
ERR: pinning maps

The following change does indeed help:

unsigned char dst[ETH_ALEN] = {0xda, 0xa6, 0xad, 0xd4, 0x27, 0xb7};

-->

unsigned char dst[ETH_ALEN+1] = {0xda, 0xa6, 0xad, 0xd4, 0x27, 0xb7};
tohojo commented 3 years ago

Okay, this was a fun one to track down :)

What happens is this: When you add a constant ({0xda, 0xa6, 0xad, 0xd4, 0x27, 0xb7}) to copy the MAC addr from, that gets stored in the .rodata section of the object file. When libbpf sees an .rodata section, it transparently creates a map to store the contents of that section. When pinning the maps, this map will also be pinned, but since its name contains a period, this fails, leading to the error you observe.

The reason making the array larger helps is that this makes the compiler think the constant is a zero-delimited string, and put it into a section called .rodata.str.1 instead, which libbpf will not create a map for (but you will notice output like libbpf: elf: skipping unrecognized data section(13) .rodata.str1.1 when loading).

So the real fix here is to fix libbpf; I'll send a patch for that. In the meantime, feel free to use the workaround of enlarging the array, but I'm going to close the pull request to include it... :)