|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +#include <net/if.h> |
| 3 | +#include <test_progs.h> |
| 4 | +#include <network_helpers.h> |
| 5 | + |
| 6 | +#define LOCAL_NETNS "xdp_dev_bound_only_netns" |
| 7 | + |
| 8 | +static int load_dummy_prog(char *name, __u32 ifindex, __u32 flags) |
| 9 | +{ |
| 10 | + struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN() }; |
| 11 | + LIBBPF_OPTS(bpf_prog_load_opts, opts); |
| 12 | + |
| 13 | + opts.prog_flags = flags; |
| 14 | + opts.prog_ifindex = ifindex; |
| 15 | + return bpf_prog_load(BPF_PROG_TYPE_XDP, name, "GPL", insns, ARRAY_SIZE(insns), &opts); |
| 16 | +} |
| 17 | + |
| 18 | +/* A test case for bpf_offload_netdev->offload handling bug: |
| 19 | + * - create a veth device (does not support offload); |
| 20 | + * - create a device bound XDP program with BPF_F_XDP_DEV_BOUND_ONLY flag |
| 21 | + * (such programs are not offloaded); |
| 22 | + * - create a device bound XDP program without flags (such programs are offloaded). |
| 23 | + * This might lead to 'BUG: kernel NULL pointer dereference'. |
| 24 | + */ |
| 25 | +void test_xdp_dev_bound_only_offdev(void) |
| 26 | +{ |
| 27 | + struct nstoken *tok = NULL; |
| 28 | + __u32 ifindex; |
| 29 | + int fd1 = -1; |
| 30 | + int fd2 = -1; |
| 31 | + |
| 32 | + SYS(out, "ip netns add " LOCAL_NETNS); |
| 33 | + tok = open_netns(LOCAL_NETNS); |
| 34 | + if (!ASSERT_OK_PTR(tok, "open_netns")) |
| 35 | + goto out; |
| 36 | + SYS(out, "ip link add eth42 type veth"); |
| 37 | + ifindex = if_nametoindex("eth42"); |
| 38 | + if (!ASSERT_NEQ(ifindex, 0, "if_nametoindex")) { |
| 39 | + perror("if_nametoindex"); |
| 40 | + goto out; |
| 41 | + } |
| 42 | + fd1 = load_dummy_prog("dummy1", ifindex, BPF_F_XDP_DEV_BOUND_ONLY); |
| 43 | + if (!ASSERT_GE(fd1, 0, "load_dummy_prog #1")) { |
| 44 | + perror("load_dummy_prog #1"); |
| 45 | + goto out; |
| 46 | + } |
| 47 | + /* Program with ifindex is considered offloaded, however veth |
| 48 | + * does not support offload => error should be reported. |
| 49 | + */ |
| 50 | + fd2 = load_dummy_prog("dummy2", ifindex, 0); |
| 51 | + ASSERT_EQ(fd2, -EINVAL, "load_dummy_prog #2 (offloaded)"); |
| 52 | + |
| 53 | +out: |
| 54 | + close(fd1); |
| 55 | + close(fd2); |
| 56 | + close_netns(tok); |
| 57 | + /* eth42 was added inside netns, removing the netns will |
| 58 | + * also remove eth42 veth pair. |
| 59 | + */ |
| 60 | + SYS_NOFAIL("ip netns del " LOCAL_NETNS); |
| 61 | +} |
0 commit comments