diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index 31962233bea1..e308b0409530 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -2150,3 +2150,33 @@ int dynptr_overwrite_ref_clone_slice_valid(void *ctx) return 0; } + +static __noinline void overwrite_clone_in_callee(struct bpf_dynptr *parent) +{ + struct bpf_dynptr clone; + + bpf_dynptr_clone(parent, &clone); + /* Overwrite the clone - parent in caller frame still holds the ref */ + *(volatile __u8 *)&clone = 0; +} + +/* + * Overwriting a clone in a callee frame should be allowed when the parent + * in the caller frame still holds the ref. dynptr_get_refcnt() currently + * only counts dynptrs in the current frame, missing the parent in the + * caller frame. + */ +SEC("?raw_tp") +__success +int dynptr_overwrite_clone_cross_frame(void *ctx) +{ + struct bpf_dynptr ptr; + + bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); + + overwrite_clone_in_callee(&ptr); + + bpf_ringbuf_discard_dynptr(&ptr, 0); + + return 0; +}