From: sashiko-bot@kernel.org
To: "Vineet Gupta" <vineet.gupta@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 09/13] bpf: track low-32 scalar equality across narrowing stack fills
Date: Thu, 10 Sep 2026 17:04:18 +0000 [thread overview]
Message-ID: <20260910170419.4C8601F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260910164635.459558-10-vineet.gupta@linux.dev>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Sign-extending loads incorrectly preserve conflicting SUBREG_ZEXT metadata.
--
commit f939550a777ae3d2a7392dec744bffdc9fabcdda
Author: Vineet Gupta <vineet.gupta@linux.dev>
bpf: track low-32 scalar equality across narrowing stack fills
This commit records a low-32 link for stack fills narrower than the wider
source, allowing the verifier to deduce relations between 32-bit narrows
and their wider origins. It also adjusts check_mem_access() to not clear
the id of a ->subreg register on a sign-extending load.
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 308ff53232f06..89be1240c99ae 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -3968,18 +3969,34 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
>
> if (size <= spill_size &&
> bpf_stack_narrow_access_ok(off, size, spill_size)) {
> - if (env->bpf_capable && size == 4 && spill_size == 4 &&
> - get_reg_width(reg) <= 32)
> + bool narrowing = get_reg_width(reg) > size * BITS_PER_BYTE;
> + /*
> + * A narrowing fill keeps only the slot's low 32 bits,
> + * so record a low-32 link rather than dropping the
> + * relation, as a 32-bit mov from a wide source does.
> + * Which kind depends on how the load fills the high
> + * half, hence is_ldsx.
> + */
> + bool subreg_link = narrowing && size == 4;
> +
> + if (env->bpf_capable && size == 4 &&
> + (subreg_link || (spill_size == 4 && !narrowing)))
> /* Ensure stack slot has an ID to build a relation
> * with the destination register on fill.
> */
> assign_scalar_id_before_mov(env, reg);
> state->regs[dst_regno] = *reg;
>
> - /* Break the relation on a narrowing fill.
> - * coerce_reg_to_size will adjust the boundaries.
> - */
> - if (get_reg_width(reg) > size * BITS_PER_BYTE)
> + if (subreg_link && reg->id)
> + state->regs[dst_regno].subreg =
> + is_ldsx ? SUBREG_SEXT : SUBREG_ZEXT;
> + else if (narrowing)
> + /*
> + * Nothing to relate: either the slot has
> + * no id to share, or the fill is narrower
> + * than the 32 bits a link can describe.
> + * coerce_reg_to_size adjusts the bounds.
> + */
> clear_scalar_id(&state->regs[dst_regno]);
[Severity: Critical]
When narrowing is false, does this preserve a stale SUBREG_ZEXT property for
a sign-extending load?
If a register with SUBREG_ZEXT is spilled to the stack and then read back
via a 4-byte sign-extending load, narrowing evaluates to false. This allows
the destination register to inherit the SUBREG_ZEXT property directly from
the stack slot, even though it is being sign-extended.
[ ... ]
> @@ -6736,13 +6753,15 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, struct b
> * Sign-extension can change the register value relative
> * to a scalar it is linked with by id (e.g. a zero-
> * extending fill of the same spilled stack slot), thus
> - * drop the shared id in that case.
> + * drop the shared id in that case. A ->subreg link is
> + * the exception: it already records that only the low
> + * 32 bits are shared, and how the high half follows.
> */
> bool no_sext = reg_umax(®s[value_regno]) <
> (1ULL << (size * BITS_PER_BYTE - 1));
>
> coerce_reg_to_size_sx(®s[value_regno], size);
> - if (!no_sext)
> + if (!no_sext && !regs[value_regno].subreg)
> clear_scalar_id(®s[value_regno]);
[Severity: Critical]
Does this check wrongly preserve the ID for SUBREG_ZEXT registers that
have just been sign-extended?
Because SUBREG_ZEXT is non-zero, !regs[value_regno].subreg evaluates to
false, skipping the clear_scalar_id() call for a register that might hold
a sign-extended negative value.
Later, if a conditional branch triggers sync_linked_regs(), it will see
SUBREG_ZEXT and invoke reconstruct_zext32(). This would forcefully set the
bounds to a zero-extended positive value.
At runtime, the discrepancy between the verifier's zero-extended positive
bounds and the actual sign-extended negative value could bypass bounds checks,
potentially leading to out-of-bounds memory reads or writes.
Should this explicitly check for SUBREG_SEXT rather than just allowing any
non-zero ->subreg value?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910164635.459558-1-vineet.gupta@linux.dev?part=9
next prev parent reply other threads:[~2026-09-10 17:04 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 16:46 [PATCH bpf-next v2 00/13] bpf: track scalar equality across the low 32 bits Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 01/13] bpf: move linked-scalar flags out of bpf_reg_state->id [NFC] Vineet Gupta
2026-09-10 17:00 ` sashiko-bot
2026-09-11 6:56 ` Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-12 18:50 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 02/13] bpf: compare linked-scalar kinds in regs_exact() Vineet Gupta
2026-09-12 18:51 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 03/13] bpf: track low-32 scalar equality across zero-extending movs Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 9:29 ` Vineet Gupta
2026-09-12 18:59 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 04/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 05/13] bpf: keep the range across a sign extension that cannot change it Vineet Gupta
2026-09-10 17:08 ` sashiko-bot
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 10:37 ` Vineet Gupta
2026-09-12 19:02 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 06/13] selftests/bpf: cover sign extensions that cannot change the range Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 07/13] bpf: track low-32 scalar equality across sign-extending movs Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 10:00 ` Vineet Gupta
2026-09-12 19:09 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 08/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 8:00 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 09/13] bpf: track low-32 scalar equality across narrowing stack fills Vineet Gupta
2026-09-10 17:04 ` sashiko-bot [this message]
2026-09-11 6:07 ` Vineet Gupta
2026-09-11 6:43 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 10/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 17:00 ` sashiko-bot
2026-09-11 5:34 ` Vineet Gupta
2026-09-10 17:31 ` bot+bpf-ci
2026-09-11 5:07 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 11/13] bpf: record what a narrowing spill actually stores Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 12/13] bpf: track low-32 scalar equality across narrowing stack spills Vineet Gupta
2026-09-10 17:05 ` sashiko-bot
2026-09-10 16:46 ` [PATCH bpf-next v2 13/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
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=20260910170419.4C8601F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vineet.gupta@linux.dev \
/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