All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Xu Yunxiang" <xyx2021@mail.ustc.edu.cn>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v4 1/2] bpf: Track iterator-owned BTF pointer lifetimes
Date: Thu, 17 Sep 2026 05:44:31 +0000	[thread overview]
Message-ID: <20260917054431.787511F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260917051948.1588826-2-xyx2021@mail.ustc.edu.cn>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] bpf: bpf_iter_next() fails to invalidate dynptrs and PTR_TO_MEM slices
- [High] bpf: PTR_TO_MEM slices returned by kfuncs escape iterator lifetime tracking
--

commit 78eae9a9dcb52a34bea55102674e78d19a5f54b8
Author: Xu Yunxiang <xyx2021@mail.ustc.edu.cn>

bpf: Track iterator-owned BTF pointer lifetimes

This commit introduces lifetime tracking for non-RCU struct iterator
results by associating PTR_TO_BTF_ID results with the iterator reference.
It invalidates the previous result when processing the next iterator
argument and propagates the backing register's lifetime for dynptrs.

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 6c6b8d8520cdf..3d47487233b75 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c

[ ... ]

> @@ -7817,6 +7834,27 @@ static bool is_kfunc_arg_iter(struct bpf_call_arg_meta *meta, int arg_idx,
>  	return btf_param_match_suffix(meta->btf, arg, "__iter");
>  }
>  
> +static int invalidate_iter_owned_btf_ptrs(struct bpf_verifier_env *env, u32 parent_id)
> +{
> +	struct bpf_func_state *unused;
> +	struct bpf_reg_state *reg;
> +	int err;
> +
> +	err = check_reference_children_leak(env, parent_id);
> +	if (err)
> +		return err;
> +
> +	/* Struct iterators can release their previous element on next. */
> +	bpf_for_each_reg_in_vstate(env->cur_state, unused, reg, ({
> +		if (base_type(reg->type) != PTR_TO_BTF_ID || reg->parent_id != parent_id)
> +			continue;
> +		bpf_diag_record_scrub(env, reg, BPF_DIAG_MOD_REF_RELEASE);
> +		mark_reg_invalid(env, reg);
> +	}));
> +
> +	return 0;
> +}

[Severity: High]
Does this code fail to invalidate dynptrs and PTR_TO_MEM slices derived
from the iterator element?

The bpf_for_each_reg_in_vstate() macro only iterates over spilled registers
using the 1 << STACK_SPILL mask, which completely skips STACK_DYNPTR slots.
Furthermore, the loop explicitly filters out anything that is not a
PTR_TO_BTF_ID.

If a BPF program constructs an unreferenced dynptr (e.g., via
bpf_dynptr_from_skb) or a PTR_TO_MEM slice from the iterator element, these
derived objects inherit the iterator's parent_id. Because they are skipped
by this logic, they will survive the bpf_iter_next() call and remain
accessible after the underlying memory is freed, potentially leading to a
use-after-free.

[ ... ]

> @@ -14446,6 +14502,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>  			regs[BPF_REG_0].btf = desc_btf;
>  			regs[BPF_REG_0].type = type;
>  			regs[BPF_REG_0].btf_id = ptr_type_id;
> +			if (bpf_is_iter_next_kfunc(&meta) && !(type & MEM_RCU))
> +				regs[BPF_REG_0].parent_id = meta.ref_obj.id;
>  		}

[Severity: High]
Can PTR_TO_MEM slices returned by kfuncs escape iterator lifetime tracking
entirely?

When an iterator element is passed to a kfunc, the verifier attempts to
propagate lifetime tracking by populating meta->ref_obj in
check_func_arg() using this check:

	if (reg_is_referenced(env, reg))
		update_ref_obj(&meta->ref_obj, reg);

However, since non-RCU iterator elements track their lifetime purely via
parent_id and have id == 0, reg_is_referenced() evaluates to false. This
leaves meta->ref_obj.id as 0.

When check_kfunc_call() processes a returned PTR_TO_MEM slice, it only
assigns parent_id if meta.ref_obj.id is non-zero:

			/* Ensures we don't access the memory after a release_reference() */
			if (meta.ref_obj.id) {
				err = validate_ref_obj(env, &meta.ref_obj);
				if (err)
					return err;
				regs[BPF_REG_0].parent_id = meta.ref_obj.id;
			}

Because meta.ref_obj.id is 0, the returned PTR_TO_MEM slice receives no
parent_id. Does this allow the slice to escape the iterator's lifetime
tracking and outlive the iterator element, causing a use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917051948.1588826-1-xyx2021@mail.ustc.edu.cn?part=1

  reply	other threads:[~2026-09-17  5:44 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-17  5:19 [PATCH bpf-next v4 0/2] bpf: Track iterator-owned BTF pointer lifetimes Xu Yunxiang
2026-09-17  5:19 ` [PATCH bpf-next v4 1/2] " Xu Yunxiang
2026-09-17  5:44   ` sashiko-bot [this message]
2026-09-17  6:48   ` bot+bpf-ci
2026-09-17 14:45   ` Alexei Starovoitov
2026-09-17  5:19 ` [PATCH bpf-next v4 2/2] selftests/bpf: Test iterator " Xu Yunxiang

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=20260917054431.787511F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=xyx2021@mail.ustc.edu.cn \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.