Message ID | 20240911033719.91468-6-lulie@linux.alibaba.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Commit | 83dff601715bdc086dc1fc470ee3aaff42215e65 |
Headers | show |
Series | bpf: Allow skb dynptr for tp_btf | expand |
On 9/10/24 8:37 PM, Philo Lu wrote: > 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> > --- > .../testing/selftests/bpf/prog_tests/dynptr.c | 36 +++++++++++++++++-- > .../testing/selftests/bpf/progs/dynptr_fail.c | 25 +++++++++++++ > .../selftests/bpf/progs/dynptr_success.c | 23 ++++++++++++ > 3 files changed, 82 insertions(+), 2 deletions(-) > > diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c > index 7cfac53c0d58d..ba40be8b1c4ef 100644 > --- a/tools/testing/selftests/bpf/prog_tests/dynptr.c > +++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c > @@ -9,6 +9,7 @@ > enum test_setup_type { > SETUP_SYSCALL_SLEEP, > SETUP_SKB_PROG, > + SETUP_SKB_PROG_TP, > }; > > static struct { > @@ -28,6 +29,7 @@ static struct { > {"test_dynptr_clone", SETUP_SKB_PROG}, > {"test_dynptr_skb_no_buff", SETUP_SKB_PROG}, > {"test_dynptr_skb_strcmp", SETUP_SKB_PROG}, > + {"test_dynptr_skb_tp_btf", SETUP_SKB_PROG_TP}, > }; > > static void verify_success(const char *prog_name, enum test_setup_type setup_type) > @@ -35,7 +37,7 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ > struct dynptr_success *skel; > struct bpf_program *prog; > struct bpf_link *link; > - int err; > + int err; > > skel = dynptr_success__open(); > if (!ASSERT_OK_PTR(skel, "dynptr_success__open")) > @@ -47,7 +49,7 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ > if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) > goto cleanup; > > - bpf_program__set_autoload(prog, true); > + bpf_program__set_autoload(prog, true); > > err = dynptr_success__load(skel); > if (!ASSERT_OK(err, "dynptr_success__load")) > @@ -87,6 +89,36 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ > > break; > } > + case SETUP_SKB_PROG_TP: > + { > + struct __sk_buff skb = {}; > + struct bpf_object *obj; > + int aux_prog_fd; > + > + /* Just use its test_run to trigger kfree_skb tracepoint */ > + err = bpf_prog_test_load("./test_pkt_access.bpf.o", BPF_PROG_TYPE_SCHED_CLS, > + &obj, &aux_prog_fd); > + if (!ASSERT_OK(err, "prog_load sched cls")) > + goto cleanup; > + > + LIBBPF_OPTS(bpf_test_run_opts, topts, > + .data_in = &pkt_v4, > + .data_size_in = sizeof(pkt_v4), > + .ctx_in = &skb, > + .ctx_size_in = sizeof(skb), > + ); > + > + link = bpf_program__attach(prog); > + if (!ASSERT_OK_PTR(link, "bpf_program__attach")) > + goto cleanup; > + > + err = bpf_prog_test_run_opts(aux_prog_fd, &topts); bpf_link__destroy(link) is needed. I fixed it and applied. Thanks. > + > + if (!ASSERT_OK(err, "test_run")) > + goto cleanup; > + > + break; > + } > }
diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c index 7cfac53c0d58d..ba40be8b1c4ef 100644 --- a/tools/testing/selftests/bpf/prog_tests/dynptr.c +++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c @@ -9,6 +9,7 @@ enum test_setup_type { SETUP_SYSCALL_SLEEP, SETUP_SKB_PROG, + SETUP_SKB_PROG_TP, }; static struct { @@ -28,6 +29,7 @@ static struct { {"test_dynptr_clone", SETUP_SKB_PROG}, {"test_dynptr_skb_no_buff", SETUP_SKB_PROG}, {"test_dynptr_skb_strcmp", SETUP_SKB_PROG}, + {"test_dynptr_skb_tp_btf", SETUP_SKB_PROG_TP}, }; static void verify_success(const char *prog_name, enum test_setup_type setup_type) @@ -35,7 +37,7 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ struct dynptr_success *skel; struct bpf_program *prog; struct bpf_link *link; - int err; + int err; skel = dynptr_success__open(); if (!ASSERT_OK_PTR(skel, "dynptr_success__open")) @@ -47,7 +49,7 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) goto cleanup; - bpf_program__set_autoload(prog, true); + bpf_program__set_autoload(prog, true); err = dynptr_success__load(skel); if (!ASSERT_OK(err, "dynptr_success__load")) @@ -87,6 +89,36 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ break; } + case SETUP_SKB_PROG_TP: + { + struct __sk_buff skb = {}; + struct bpf_object *obj; + int aux_prog_fd; + + /* Just use its test_run to trigger kfree_skb tracepoint */ + err = bpf_prog_test_load("./test_pkt_access.bpf.o", BPF_PROG_TYPE_SCHED_CLS, + &obj, &aux_prog_fd); + if (!ASSERT_OK(err, "prog_load sched cls")) + goto cleanup; + + LIBBPF_OPTS(bpf_test_run_opts, topts, + .data_in = &pkt_v4, + .data_size_in = sizeof(pkt_v4), + .ctx_in = &skb, + .ctx_size_in = sizeof(skb), + ); + + link = bpf_program__attach(prog); + if (!ASSERT_OK_PTR(link, "bpf_program__attach")) + goto cleanup; + + err = bpf_prog_test_run_opts(aux_prog_fd, &topts); + + if (!ASSERT_OK(err, "test_run")) + goto cleanup; + + break; + } } ASSERT_EQ(skel->bss->err, 0, "err"); diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index 68b8c6eca5083..8f36c9de75915 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -6,6 +6,7 @@ #include <stdbool.h> #include <linux/bpf.h> #include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> #include <linux/if_ether.h> #include "bpf_misc.h" #include "bpf_kfuncs.h" @@ -1254,6 +1255,30 @@ int skb_invalid_ctx(void *ctx) return 0; } +SEC("fentry/skb_tx_error") +__failure __msg("must be referenced or trusted") +int BPF_PROG(skb_invalid_ctx_fentry, void *skb) +{ + struct bpf_dynptr ptr; + + /* this should fail */ + bpf_dynptr_from_skb(skb, 0, &ptr); + + return 0; +} + +SEC("fexit/skb_tx_error") +__failure __msg("must be referenced or trusted") +int BPF_PROG(skb_invalid_ctx_fexit, void *skb) +{ + struct bpf_dynptr ptr; + + /* this should fail */ + bpf_dynptr_from_skb(skb, 0, &ptr); + + return 0; +} + /* Reject writes to dynptr slot for uninit arg */ SEC("?raw_tp") __failure __msg("potential write to dynptr at off=-16") diff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c index 5985920d162e7..bfcc85686cf04 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_success.c +++ b/tools/testing/selftests/bpf/progs/dynptr_success.c @@ -5,6 +5,7 @@ #include <stdbool.h> #include <linux/bpf.h> #include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> #include "bpf_misc.h" #include "bpf_kfuncs.h" #include "errno.h" @@ -544,3 +545,25 @@ int test_dynptr_skb_strcmp(struct __sk_buff *skb) return 1; } + +SEC("tp_btf/kfree_skb") +int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location) +{ + __u8 write_data[2] = {1, 2}; + struct bpf_dynptr ptr; + int ret; + + if (bpf_dynptr_from_skb(skb, 0, &ptr)) { + err = 1; + return 1; + } + + /* since tp_btf skbs are read only, writes should fail */ + ret = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); + if (ret != -EINVAL) { + err = 2; + return 1; + } + + return 1; +}
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> --- .../testing/selftests/bpf/prog_tests/dynptr.c | 36 +++++++++++++++++-- .../testing/selftests/bpf/progs/dynptr_fail.c | 25 +++++++++++++ .../selftests/bpf/progs/dynptr_success.c | 23 ++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)