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

selftests/bpf: validate struct_ops early failure detection logic

Add a simple test that validates that libbpf will reject isolated
struct_ops program early with helpful warning message.

Also validate that explicit use of such BPF program through BPF skeleton
after BPF object is open won't trigger any warnings.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20240507001335.1445325-7-andrii@kernel.org
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Andrii Nakryiko and committed by
Martin KaFai Lau
41df0733 c78420ba

+64
+45
tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c
··· 5 5 6 6 #include "struct_ops_module.skel.h" 7 7 #include "struct_ops_nulled_out_cb.skel.h" 8 + #include "struct_ops_forgotten_cb.skel.h" 8 9 9 10 static void check_map_info(struct bpf_map_info *info) 10 11 { ··· 200 199 struct_ops_nulled_out_cb__destroy(skel); 201 200 } 202 201 202 + /* validate that libbpf generates reasonable error message if struct_ops is 203 + * not referenced in any struct_ops map 204 + */ 205 + static void test_struct_ops_forgotten_cb(void) 206 + { 207 + struct struct_ops_forgotten_cb *skel; 208 + char *log; 209 + int err; 210 + 211 + skel = struct_ops_forgotten_cb__open(); 212 + if (!ASSERT_OK_PTR(skel, "skel_open")) 213 + return; 214 + 215 + start_libbpf_log_capture(); 216 + 217 + err = struct_ops_forgotten_cb__load(skel); 218 + if (!ASSERT_ERR(err, "skel_load")) 219 + goto cleanup; 220 + 221 + log = stop_libbpf_log_capture(); 222 + ASSERT_HAS_SUBSTR(log, 223 + "prog 'test_1_forgotten': SEC(\"struct_ops\") program isn't referenced anywhere, did you forget to use it?", 224 + "libbpf_log"); 225 + free(log); 226 + 227 + struct_ops_forgotten_cb__destroy(skel); 228 + 229 + /* now let's programmatically use it, we should be fine now */ 230 + skel = struct_ops_forgotten_cb__open(); 231 + if (!ASSERT_OK_PTR(skel, "skel_open")) 232 + return; 233 + 234 + skel->struct_ops.ops->test_1 = skel->progs.test_1_forgotten; /* not anymore */ 235 + 236 + err = struct_ops_forgotten_cb__load(skel); 237 + if (!ASSERT_OK(err, "skel_load")) 238 + goto cleanup; 239 + 240 + cleanup: 241 + struct_ops_forgotten_cb__destroy(skel); 242 + } 243 + 203 244 void serial_test_struct_ops_module(void) 204 245 { 205 246 if (test__start_subtest("test_struct_ops_load")) ··· 252 209 test_struct_ops_incompatible(); 253 210 if (test__start_subtest("test_struct_ops_null_out_cb")) 254 211 test_struct_ops_nulled_out_cb(); 212 + if (test__start_subtest("struct_ops_forgotten_cb")) 213 + test_struct_ops_forgotten_cb(); 255 214 } 256 215
+19
tools/testing/selftests/bpf/progs/struct_ops_forgotten_cb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + #include <vmlinux.h> 4 + #include <bpf/bpf_tracing.h> 5 + #include "../bpf_testmod/bpf_testmod.h" 6 + 7 + char _license[] SEC("license") = "GPL"; 8 + 9 + SEC("struct_ops/test_1") 10 + int BPF_PROG(test_1_forgotten) 11 + { 12 + return 0; 13 + } 14 + 15 + SEC(".struct_ops.link") 16 + struct bpf_testmod_ops ops = { 17 + /* we forgot to reference test_1_forgotten above, oops */ 18 + }; 19 +