BPF List
 help / color / mirror / Atom feed
From: Eduard Zingerman <eddyz87@gmail.com>
To: Amery Hung <ameryhung@gmail.com>, bpf@vger.kernel.org
Cc: netdev@vger.kernel.org, alexei.starovoitov@gmail.com,
	andrii@kernel.org, daniel@iogearbox.net, memxor@gmail.com,
	martin.lau@kernel.org,  mykyta.yatsenko5@gmail.com,
	kernel-team@meta.com
Subject: Re: [PATCH bpf-next v4 05/12] bpf: Refactor object relationship tracking and fix dynptr UAF bug
Date: Mon, 11 May 2026 19:28:06 -0700	[thread overview]
Message-ID: <ae5f8053bfc94fb02abdf78d5a452a7baae5c35e.camel@gmail.com> (raw)
In-Reply-To: <20260506142709.2298255-6-ameryhung@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2919 bytes --]

On Wed, 2026-05-06 at 07:27 -0700, Amery Hung wrote:

[...]

> +/* Release id and objects referencing the id iteratively in a DFS manner */
> +static int release_reference(struct bpf_verifier_env *env, int id)
> +{
> +	u32 mask = (1 << STACK_SPILL) | (1 << STACK_DYNPTR);
>  	struct bpf_verifier_state *vstate = env->cur_state;
> +	struct bpf_idmap *idstack = &env->idmap_scratch;
> +	struct bpf_stack_state *stack;
>  	struct bpf_func_state *state;
>  	struct bpf_reg_state *reg;
> -	int err;
> +	int root_id = id, err;
>  
> -	err = release_reference_nomark(vstate, ref_obj_id);
> -	if (err)
> -		return err;
> +	idstack->cnt = 0;
> +	idstack_push(idstack, id);
>  
> -	bpf_for_each_reg_in_vstate(vstate, state, reg, ({
> -		if (reg->ref_obj_id == ref_obj_id)
> -			mark_reg_invalid(env, reg);
> -	}));
> +	if (find_reference_state(vstate, id))
> +		WARN_ON_ONCE(release_reference_nomark(vstate, id));
> +
> +	while ((id = idstack_pop(idstack))) {
> +		bpf_for_each_reg_in_vstate_mask(vstate, state, reg, stack, mask, ({
> +			int ref_obj_cnt = 1;
> +
> +			if (reg->id != id && reg->parent_id != id && reg->ref_obj_id != id)
> +				continue;
> +
> +			/*
> +			 * A referenced dynptr can be overwritten only if there is at
> +			 * least one other dynptr sharing the same ref_obj_id,
> +			 * ensuring the reference can still be properly released.
> +			 */
> +			if (stack && stack->slot_type[BPF_REG_SIZE - 1] == STACK_DYNPTR &&
> +			    dynptr_type_referenced(reg->dynptr.type))
> +				ref_obj_cnt = dynptr_get_refcnt(state, reg->ref_obj_id);

Note that dynptr_get_refcnt() only looks for objects in the state's frame,
dynptrs in other frames are ignored. This can lead to false rejections,
as in the attached test cases, which verifier refuses to load with the
following error message:

; *(volatile __u8 *)&clone = 0; @ dynptr_fail.c:2160
19: (73) *(u8 *)(r10 -16) = r1
Leaking reference id=2 alloc_insn=7. Release it first.
processed 14 insns (limit 1000000) max_states_per_insn 1 total_states 1 peak_states 1 mark_read 0

> +
> +			if (reg->ref_obj_id && reg->ref_obj_id != root_id && ref_obj_cnt <= 1) {
> +				struct bpf_reference_state *ref_state;
> +
> +				ref_state = find_reference_state(env->cur_state, reg->ref_obj_id);
> +				verbose(env, "Leaking reference id=%d alloc_insn=%d. Release it first.\n",
> +					ref_state->id, ref_state->insn_idx);
> +				return -EINVAL;
> +			}
> +
> +			/* Free objects derived from the current object */
> +			if (reg->id != id) {
> +				err = idstack_push(idstack, reg->id);
> +				if (err)
> +					return err;
> +			}
> +
> +			if (!stack || stack->slot_type[BPF_REG_SIZE - 1] == STACK_SPILL)
> +				mark_reg_invalid(env, reg);
> +			else if (stack->slot_type[BPF_REG_SIZE - 1] == STACK_DYNPTR)
> +				invalidate_dynptr(env, stack);
> +		}));
> +	}
>  
>  	return 0;
>  }

[...]

[-- Attachment #2: false-positivie-test.patch --]
[-- Type: text/x-patch, Size: 1116 bytes --]

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;
+}

  parent reply	other threads:[~2026-05-12  2:28 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-06 14:26 [PATCH bpf-next v4 00/12] Refactor verifier object relationship tracking Amery Hung
2026-05-06 14:26 ` [PATCH bpf-next v4 01/12] bpf: Simplify mark_stack_slot_obj_read() and callers Amery Hung
2026-05-11 17:17   ` Eduard Zingerman
2026-05-12 20:13     ` Amery Hung
2026-05-06 14:26 ` [PATCH bpf-next v4 02/12] bpf: Unify dynptr handling in the verifier Amery Hung
2026-05-06 15:27   ` bot+bpf-ci
2026-05-07 12:22     ` Amery Hung
2026-05-06 14:26 ` [PATCH bpf-next v4 03/12] bpf: Assign reg->id when getting referenced kptr from ctx Amery Hung
2026-05-06 15:27   ` bot+bpf-ci
2026-05-07 12:38     ` Amery Hung
2026-05-11 21:31   ` Eduard Zingerman
2026-05-06 14:27 ` [PATCH bpf-next v4 04/12] bpf: Preserve reg->id of pointer objects after null-check Amery Hung
2026-05-11 21:48   ` Eduard Zingerman
2026-05-06 14:27 ` [PATCH bpf-next v4 05/12] bpf: Refactor object relationship tracking and fix dynptr UAF bug Amery Hung
2026-05-06 15:27   ` bot+bpf-ci
2026-05-07 12:20     ` Amery Hung
2026-05-06 21:54   ` sashiko-bot
2026-05-07 12:52     ` Amery Hung
2026-05-12  2:28   ` Eduard Zingerman [this message]
2026-05-06 14:27 ` [PATCH bpf-next v4 06/12] bpf: Remove redundant dynptr arg check for helper Amery Hung
2026-05-12 18:32   ` Eduard Zingerman
2026-05-06 14:27 ` [PATCH bpf-next v4 07/12] bpf: Unify referenced object tracking in verifier Amery Hung
2026-05-06 22:48   ` sashiko-bot
2026-05-07 12:55     ` Amery Hung
2026-05-12 19:03   ` Eduard Zingerman
2026-05-12 20:37     ` Amery Hung
2026-05-12 21:09       ` Eduard Zingerman
2026-05-12 21:27         ` Amery Hung
2026-05-12 21:28           ` Eduard Zingerman
2026-05-12 21:31             ` Amery Hung
2026-05-06 14:27 ` [PATCH bpf-next v4 08/12] bpf: Unify release handling for helpers and kfuncs Amery Hung
2026-05-06 23:59   ` sashiko-bot
2026-05-07 13:23     ` Amery Hung
2026-05-12 20:19   ` Eduard Zingerman
2026-05-12 21:22     ` Amery Hung
2026-05-12 21:25       ` Eduard Zingerman
2026-05-06 14:27 ` [PATCH bpf-next v4 09/12] selftests/bpf: Test creating dynptr from dynptr data and slice Amery Hung
2026-05-06 14:27 ` [PATCH bpf-next v4 10/12] selftests/bpf: Test using dynptr after freeing the underlying object Amery Hung
2026-05-06 14:27 ` [PATCH bpf-next v4 11/12] selftests/bpf: Test using slice after invalidating dynptr clone Amery Hung
2026-05-06 14:27 ` [PATCH bpf-next v4 12/12] selftests/bpf: Test using file dynptr after the reference on file is dropped Amery Hung

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ae5f8053bfc94fb02abdf78d5a452a7baae5c35e.camel@gmail.com \
    --to=eddyz87@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=ameryhung@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@meta.com \
    --cc=martin.lau@kernel.org \
    --cc=memxor@gmail.com \
    --cc=mykyta.yatsenko5@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox