Add a few tests to capture source object relationship with dynptr and their slices and ensure invalidation of everything works correctly. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> --- .../testing/selftests/bpf/prog_tests/dynptr.c | 2 + .../testing/selftests/bpf/progs/dynptr_fail.c | 1 + .../selftests/bpf/progs/dynptr_fail_qdisc.c | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/dynptr_fail_qdisc.c diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c index e29cc16124c2..929355de1002 100644 --- a/tools/testing/selftests/bpf/prog_tests/dynptr.c +++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c @@ -4,6 +4,7 @@ #include <test_progs.h> #include <network_helpers.h> #include "dynptr_fail.skel.h" +#include "dynptr_fail_qdisc.skel.h" #include "dynptr_success.skel.h" enum test_setup_type { @@ -161,4 +162,5 @@ void test_dynptr(void) } RUN_TESTS(dynptr_fail); + RUN_TESTS(dynptr_fail_qdisc); } diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index 345e704e5346..7c67797a5aac 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -8,6 +8,7 @@ #include <bpf/bpf_tracing.h> #include "bpf_misc.h" #include "bpf_kfuncs.h" +#include "bpf_experimental.h" char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail_qdisc.c b/tools/testing/selftests/bpf/progs/dynptr_fail_qdisc.c new file mode 100644 index 000000000000..fc222213f572 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/dynptr_fail_qdisc.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ +#include <vmlinux.h> +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include "bpf_misc.h" +#include "bpf_experimental.h" + +char _license[] SEC("license") = "GPL"; + +/* + * Putting these tests in dynptr_fail.c causes other random tests to fail, + * keep them in their isolated CU. + */ + +SEC("?struct_ops") +__failure __msg("invalid mem access 'scalar'") +int BPF_PROG(test_dynptr_source_release, struct sk_buff *skb, + struct Qdisc *sch, struct bpf_sk_buff_ptr *to_free) +{ + struct bpf_dynptr dptr, dptr2; + char buf[8], *data; + + bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &dptr); + bpf_dynptr_read(buf, sizeof(buf), &dptr, 0, 0); + bpf_dynptr_clone(&dptr, &dptr2); + data = bpf_dynptr_slice(&dptr2, 0, buf, sizeof(buf)); + bpf_qdisc_skb_drop(skb, to_free); + /* These reads/writes now succeed since dynptr is destroyed. */ + *(char *)&dptr = *(char *)&dptr2; + return *data; +} + +SEC("?.struct_ops") +struct Qdisc_ops test_dynptr_qdisc = { + .enqueue = (void *)test_dynptr_source_release, + .id = "bpf_fq", +}; -- 2.47.1