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

selftests/bpf: Expand skb dynptr selftests for tp_btf

Add 3 test cases for skb dynptr used in tp_btf:
- test_dynptr_skb_tp_btf: use skb dynptr in tp_btf and make sure it is
read-only.
- skb_invalid_ctx_fentry/skb_invalid_ctx_fexit: bpf_dynptr_from_skb
should fail in fentry/fexit.

In test_dynptr_skb_tp_btf, to trigger the tracepoint in kfree_skb,
test_pkt_access is used for its test_run, as in kfree_skb.c. Because the
test process is different from others, a new setup type is defined,
i.e., SETUP_SKB_PROG_TP.

The result is like:
$ ./test_progs -t 'dynptr/test_dynptr_skb_tp_btf'
#84/14 dynptr/test_dynptr_skb_tp_btf:OK
#84 dynptr:OK
#127 kfunc_dynptr_param:OK
Summary: 2/1 PASSED, 0 SKIPPED, 0 FAILED

$ ./test_progs -t 'dynptr/skb_invalid_ctx_f'
#84/85 dynptr/skb_invalid_ctx_fentry:OK
#84/86 dynptr/skb_invalid_ctx_fexit:OK
#84 dynptr:OK
#127 kfunc_dynptr_param:OK
Summary: 2/2 PASSED, 0 SKIPPED, 0 FAILED

Also fix two coding style nits (change spaces to tabs).

Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
Link: https://lore.kernel.org/r/20240911033719.91468-6-lulie@linux.alibaba.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Philo Lu and committed by
Martin KaFai Lau
83dff601 ffc83860

+83 -2
+35 -2
tools/testing/selftests/bpf/prog_tests/dynptr.c
··· 9 9 enum test_setup_type { 10 10 SETUP_SYSCALL_SLEEP, 11 11 SETUP_SKB_PROG, 12 + SETUP_SKB_PROG_TP, 12 13 }; 13 14 14 15 static struct { ··· 29 28 {"test_dynptr_clone", SETUP_SKB_PROG}, 30 29 {"test_dynptr_skb_no_buff", SETUP_SKB_PROG}, 31 30 {"test_dynptr_skb_strcmp", SETUP_SKB_PROG}, 31 + {"test_dynptr_skb_tp_btf", SETUP_SKB_PROG_TP}, 32 32 }; 33 33 34 34 static void verify_success(const char *prog_name, enum test_setup_type setup_type) ··· 37 35 struct dynptr_success *skel; 38 36 struct bpf_program *prog; 39 37 struct bpf_link *link; 40 - int err; 38 + int err; 41 39 42 40 skel = dynptr_success__open(); 43 41 if (!ASSERT_OK_PTR(skel, "dynptr_success__open")) ··· 49 47 if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) 50 48 goto cleanup; 51 49 52 - bpf_program__set_autoload(prog, true); 50 + bpf_program__set_autoload(prog, true); 53 51 54 52 err = dynptr_success__load(skel); 55 53 if (!ASSERT_OK(err, "dynptr_success__load")) ··· 83 81 goto cleanup; 84 82 85 83 err = bpf_prog_test_run_opts(prog_fd, &topts); 84 + 85 + if (!ASSERT_OK(err, "test_run")) 86 + goto cleanup; 87 + 88 + break; 89 + } 90 + case SETUP_SKB_PROG_TP: 91 + { 92 + struct __sk_buff skb = {}; 93 + struct bpf_object *obj; 94 + int aux_prog_fd; 95 + 96 + /* Just use its test_run to trigger kfree_skb tracepoint */ 97 + err = bpf_prog_test_load("./test_pkt_access.bpf.o", BPF_PROG_TYPE_SCHED_CLS, 98 + &obj, &aux_prog_fd); 99 + if (!ASSERT_OK(err, "prog_load sched cls")) 100 + goto cleanup; 101 + 102 + LIBBPF_OPTS(bpf_test_run_opts, topts, 103 + .data_in = &pkt_v4, 104 + .data_size_in = sizeof(pkt_v4), 105 + .ctx_in = &skb, 106 + .ctx_size_in = sizeof(skb), 107 + ); 108 + 109 + link = bpf_program__attach(prog); 110 + if (!ASSERT_OK_PTR(link, "bpf_program__attach")) 111 + goto cleanup; 112 + 113 + err = bpf_prog_test_run_opts(aux_prog_fd, &topts); 114 + bpf_link__destroy(link); 86 115 87 116 if (!ASSERT_OK(err, "test_run")) 88 117 goto cleanup;
+25
tools/testing/selftests/bpf/progs/dynptr_fail.c
··· 6 6 #include <stdbool.h> 7 7 #include <linux/bpf.h> 8 8 #include <bpf/bpf_helpers.h> 9 + #include <bpf/bpf_tracing.h> 9 10 #include <linux/if_ether.h> 10 11 #include "bpf_misc.h" 11 12 #include "bpf_kfuncs.h" ··· 1251 1250 1252 1251 /* this should fail */ 1253 1252 bpf_dynptr_from_skb(ctx, 0, &ptr); 1253 + 1254 + return 0; 1255 + } 1256 + 1257 + SEC("fentry/skb_tx_error") 1258 + __failure __msg("must be referenced or trusted") 1259 + int BPF_PROG(skb_invalid_ctx_fentry, void *skb) 1260 + { 1261 + struct bpf_dynptr ptr; 1262 + 1263 + /* this should fail */ 1264 + bpf_dynptr_from_skb(skb, 0, &ptr); 1265 + 1266 + return 0; 1267 + } 1268 + 1269 + SEC("fexit/skb_tx_error") 1270 + __failure __msg("must be referenced or trusted") 1271 + int BPF_PROG(skb_invalid_ctx_fexit, void *skb) 1272 + { 1273 + struct bpf_dynptr ptr; 1274 + 1275 + /* this should fail */ 1276 + bpf_dynptr_from_skb(skb, 0, &ptr); 1254 1277 1255 1278 return 0; 1256 1279 }
+23
tools/testing/selftests/bpf/progs/dynptr_success.c
··· 5 5 #include <stdbool.h> 6 6 #include <linux/bpf.h> 7 7 #include <bpf/bpf_helpers.h> 8 + #include <bpf/bpf_tracing.h> 8 9 #include "bpf_misc.h" 9 10 #include "bpf_kfuncs.h" 10 11 #include "errno.h" ··· 540 539 data = bpf_dynptr_slice(&ptr, 0, NULL, 10); 541 540 if (data) { 542 541 bpf_strncmp(data, 10, "foo"); 542 + return 1; 543 + } 544 + 545 + return 1; 546 + } 547 + 548 + SEC("tp_btf/kfree_skb") 549 + int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location) 550 + { 551 + __u8 write_data[2] = {1, 2}; 552 + struct bpf_dynptr ptr; 553 + int ret; 554 + 555 + if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 556 + err = 1; 557 + return 1; 558 + } 559 + 560 + /* since tp_btf skbs are read only, writes should fail */ 561 + ret = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); 562 + if (ret != -EINVAL) { 563 + err = 2; 543 564 return 1; 544 565 } 545 566