Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add test case for different expected_attach_type

Add a small test case which adds two programs - one calling the other
through a tailcall - and check that BPF rejects them in case of different
expected_attach_type values:

# ./vmtest.sh -- ./test_progs -t xdp_devmap
[...]
#641/1 xdp_devmap_attach/DEVMAP with programs in entries:OK
#641/2 xdp_devmap_attach/DEVMAP with frags programs in entries:OK
#641/3 xdp_devmap_attach/Verifier check of DEVMAP programs:OK
#641/4 xdp_devmap_attach/DEVMAP with programs in entries on veth:OK
#641 xdp_devmap_attach:OK
Summary: 2/4 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20250926171201.188490-2-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
0e8e60e8 4540aed5

+59 -1
+30 -1
tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
··· 7 7 #include <test_progs.h> 8 8 9 9 #include "test_xdp_devmap_helpers.skel.h" 10 + #include "test_xdp_devmap_tailcall.skel.h" 10 11 #include "test_xdp_with_devmap_frags_helpers.skel.h" 11 12 #include "test_xdp_with_devmap_helpers.skel.h" 12 13 ··· 106 105 "Load of XDP program accessing egress ifindex without attach type")) { 107 106 test_xdp_devmap_helpers__destroy(skel); 108 107 } 108 + } 109 + 110 + static void test_xdp_devmap_tailcall(enum bpf_attach_type prog_dev, 111 + enum bpf_attach_type prog_tail, 112 + bool expect_reject) 113 + { 114 + struct test_xdp_devmap_tailcall *skel; 115 + int err; 116 + 117 + skel = test_xdp_devmap_tailcall__open(); 118 + if (!ASSERT_OK_PTR(skel, "test_xdp_devmap_tailcall__open")) 119 + return; 120 + 121 + bpf_program__set_expected_attach_type(skel->progs.xdp_devmap, prog_dev); 122 + bpf_program__set_expected_attach_type(skel->progs.xdp_entry, prog_tail); 123 + 124 + err = test_xdp_devmap_tailcall__load(skel); 125 + if (expect_reject) 126 + ASSERT_ERR(err, "test_xdp_devmap_tailcall__load"); 127 + else 128 + ASSERT_OK(err, "test_xdp_devmap_tailcall__load"); 129 + 130 + test_xdp_devmap_tailcall__destroy(skel); 109 131 } 110 132 111 133 static void test_xdp_with_devmap_frags_helpers(void) ··· 262 238 if (test__start_subtest("DEVMAP with frags programs in entries")) 263 239 test_xdp_with_devmap_frags_helpers(); 264 240 265 - if (test__start_subtest("Verifier check of DEVMAP programs")) 241 + if (test__start_subtest("Verifier check of DEVMAP programs")) { 266 242 test_neg_xdp_devmap_helpers(); 243 + test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, BPF_XDP_DEVMAP, false); 244 + test_xdp_devmap_tailcall(0, 0, true); 245 + test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, 0, true); 246 + test_xdp_devmap_tailcall(0, BPF_XDP_DEVMAP, true); 247 + } 267 248 268 249 if (test__start_subtest("DEVMAP with programs in entries on veth")) 269 250 test_xdp_with_devmap_helpers_veth();
+29
tools/testing/selftests/bpf/progs/test_xdp_devmap_tailcall.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include "vmlinux.h" 4 + #include <bpf/bpf_helpers.h> 5 + #include <bpf/bpf_tracing.h> 6 + 7 + SEC("xdp") 8 + int xdp_devmap(struct xdp_md *ctx) 9 + { 10 + return ctx->egress_ifindex; 11 + } 12 + 13 + struct { 14 + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 15 + __uint(max_entries, 1); 16 + __uint(key_size, sizeof(__u32)); 17 + __array(values, int (void *)); 18 + } xdp_map SEC(".maps") = { 19 + .values = { 20 + [0] = (void *)&xdp_devmap, 21 + }, 22 + }; 23 + 24 + SEC("xdp") 25 + int xdp_entry(struct xdp_md *ctx) 26 + { 27 + bpf_tail_call(ctx, &xdp_map, 0); 28 + return 0; 29 + }