]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Remove redundant dynptr arg check for helper
authorAmery Hung <ameryhung@gmail.com>
Fri, 29 May 2026 01:49:29 +0000 (18:49 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 2 Jun 2026 01:31:41 +0000 (18:31 -0700)
unmark_stack_slots_dynptr() already makes sure that CONST_PTR_TO_DYNPTR
cannot be released. process_dynptr_func() also prevents passing
uninitialized dynptr to helpers expecting initialized dynptr. Now that
unmark_stack_slots_dynptr() also reports error returned from
release_reference(), there should be no reason to keep these redundant
checks.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/r/20260529014936.2811085-7-ameryhung@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c
tools/testing/selftests/bpf/progs/dynptr_fail.c
tools/testing/selftests/bpf/progs/user_ringbuf_fail.c

index 6d82ca5acacb8fd158c179e9004c9dff4e940ce3..4f75e5f95d2773192cba893ec67b5fd17568e7d9 100644 (file)
@@ -8220,26 +8220,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 
 skip_type_check:
        if (arg_type_is_release(arg_type)) {
-               if (arg_type_is_dynptr(arg_type)) {
-                       struct bpf_func_state *state = bpf_func(env, reg);
-                       int spi;
-
-                       /* Only dynptr created on stack can be released, thus
-                        * the get_spi and stack state checks for spilled_ptr
-                        * should only be done before process_dynptr_func for
-                        * PTR_TO_STACK.
-                        */
-                       if (reg->type == PTR_TO_STACK) {
-                               spi = dynptr_get_spi(env, reg);
-                               if (spi < 0 || !state->stack[spi].spilled_ptr.id) {
-                                       verbose(env, "arg %d is an unacquired reference\n", regno);
-                                       return -EINVAL;
-                               }
-                       } else {
-                               verbose(env, "cannot release unowned const bpf_dynptr\n");
-                               return -EINVAL;
-                       }
-               } else if (!reg_is_referenced(env, reg) && !bpf_register_is_null(reg)) {
+               if (!arg_type_is_dynptr(arg_type) && !reg_is_referenced(env, reg) && !bpf_register_is_null(reg)) {
                        verbose(env, "R%d must be referenced when passed to release function\n",
                                regno);
                        return -EINVAL;
index fa0beeaad1be0f4ab6126f79c1aea9037677ea69..40a14a5174a53e83d75b3dfc606ff34bbf4ef10f 100644 (file)
@@ -136,7 +136,7 @@ int ringbuf_missing_release_callback(void *ctx)
 
 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
 SEC("?raw_tp")
-__failure __msg("arg 1 is an unacquired reference")
+__failure __msg("Expected an initialized dynptr as R1")
 int ringbuf_release_uninit_dynptr(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -650,7 +650,7 @@ int invalid_offset(void *ctx)
 
 /* Can't release a dynptr twice */
 SEC("?raw_tp")
-__failure __msg("arg 1 is an unacquired reference")
+__failure __msg("Expected an initialized dynptr as R1")
 int release_twice(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -677,7 +677,7 @@ static int release_twice_callback_fn(__u32 index, void *data)
  * within a callback function, fails
  */
 SEC("?raw_tp")
-__failure __msg("arg 1 is an unacquired reference")
+__failure __msg("Expected an initialized dynptr as R1")
 int release_twice_callback(void *ctx)
 {
        struct bpf_dynptr ptr;
index 54de0389f8785a463d06231cc50ca558d47f9e03..c0d0422b8030b24d8a45a3486e14156c48e47a2d 100644 (file)
@@ -146,7 +146,7 @@ try_discard_dynptr(struct bpf_dynptr *dynptr, void *context)
  * not be able to read past the end of the pointer.
  */
 SEC("?raw_tp")
-__failure __msg("cannot release unowned const bpf_dynptr")
+__failure __msg("CONST_PTR_TO_DYNPTR cannot be released")
 int user_ringbuf_callback_discard_dynptr(void *ctx)
 {
        bpf_user_ringbuf_drain(&user_ringbuf, try_discard_dynptr, NULL, 0);
@@ -166,7 +166,7 @@ try_submit_dynptr(struct bpf_dynptr *dynptr, void *context)
  * not be able to read past the end of the pointer.
  */
 SEC("?raw_tp")
-__failure __msg("cannot release unowned const bpf_dynptr")
+__failure __msg("CONST_PTR_TO_DYNPTR cannot be released")
 int user_ringbuf_callback_submit_dynptr(void *ctx)
 {
        bpf_user_ringbuf_drain(&user_ringbuf, try_submit_dynptr, NULL, 0);