From: sashiko-bot@kernel.org
To: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>, bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 20/29] bpf: Find a copy of an induction variable without scalar ids
Date: Wed, 11 Nov 2026 05:57:25 +0000 [thread overview]
Message-ID: <sashiko-outbox-208372@kernel.org> (raw)
In-Reply-To: <20261111051341.2800252-21-alexei.starovoitov@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [High] bpf: type confusion between pointer and scalar bounds in
is_iv_at_header()
--
commit a899486291f489b60aa159499a2316c95dbc938e
Author: Alexei Starovoitov <ast@kernel.org>
bpf: Find a copy of an induction variable without scalar ids
This commit replaces COPY_SCEV and scalar ID checks for induction variable
copies with untyped expression comparisons via const_diff_at_header().
> diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c
> index 98a05f97196a6..28fd06c16fe4d 100644
> --- a/kernel/bpf/scev.c
> +++ b/kernel/bpf/scev.c
[ ... ]
> @@ -4585,6 +4518,19 @@ static void linear_bounds(struct bpf_reg_state *reg, u32 max_header_count,
> out->r32 = r32;
> }
>
> +/*
> + * Is @r the induction variable that the latch tests, or congruent to it: equal to it at the header
> + * of the loop at @h in every iteration? Then the range of the one is the range of the other.
> + */
> +static bool is_iv_at_header(struct bpf_verifier_env *env, int h, int iv_reg, u32 r)
> +{
> + s64 delta;
> +
> + if (iv_reg < 0)
> + return false;
> + return r == iv_reg || (const_diff_at_header(env, h, iv_reg, r, &delta) && !delta);
> +}
> +
> static void iv_bounds(struct bounds *bounds, struct cnum64 iv_range)
> {
> struct cnum64 r64 = cnum64_intersect(bounds->r64, iv_range);
[ ... ]
> @@ -5128,7 +5074,7 @@ int bpf_widen_scev_regs(struct bpf_verifier_env *env, struct bpf_verifier_state
> if (err)
> return err;
> linear_bounds(reg, iters->max_header_count, &coefs, &bounds);
> - if (coefs.base_reg == iters->iv_reg)
> + if (is_iv_at_header(env, insn_idx, iters->iv_reg, coefs.base_reg))
> iv_bounds(&bounds, iters->iv_range);
> if (log->level & BPF_LOG_LEVEL2) {
> bpf_log(log, "loop header at %d, widening ", insn_idx);
[ ... ]
> @@ -5251,7 +5196,11 @@ int bpf_clamp_scev_regs(struct bpf_verifier_env *env, struct bpf_func_state *cur
> continue;
> clamp:
> linear_bounds(entry_reg, max_header_count, &coefs, &bounds);
> - if (coefs.base_reg == entry->iv_reg && !moved)
> + /*
> + * iv_range is the range at the header. After the latch @r can be the zero extension
> + * of its header value. @reg went through that insn and has what holds of the range.
> + */
> + if (!behind && is_iv_at_header(env, insn_idx, entry->iv_reg, coefs.base_reg))
> iv_bounds(&bounds, entry->iv_range);
> if (moved) {
> /* a sum that can wrap has another residue, see scalar_step_add() */
[Severity: High]
Can is_iv_at_header() apply a pointer induction variable's offset range
(iv_range) to a congruent SCALAR_VALUE register?
const_diff_at_header() compares untyped SCEV expressions without checking
that iv_reg and r have the same register type in the loop-entry state. In
transfer(), a no-op 64-bit BPF_ALU | BPF_END (such as le64 on a
little-endian host) leaves reg2expr[dst] unchanged:
kernel/bpf/scev.c:transfer() {
...
need_bswap = class == BPF_ALU64 || ((x_or_k == BPF_TO_LE) != little_endian);
switch (insn->imm) {
case 16: op = need_bswap ? BSWAP16 : ZEXT16; break;
case 32: op = need_bswap ? BSWAP32 : ZEXT32; break;
case 64: op = need_bswap ? BSWAP64 : 0; break;
...
id = reg2expr[dst];
if (op)
id = expr1(scev, op, reg2expr[dst]);
return replace_reg(scev, e, dst, id);
}
When env->allow_ptr_leaks is enabled, check_alu_op() degrades a pointer
register passed to that instruction to an unknown SCALAR_VALUE while the
instruction preserves the raw 64-bit pointer value at runtime.
If iv_reg is a pointer induction variable (for example PTR_TO_MAP_VALUE
with offset in [1, 10]) and r is copied from iv_reg and passed through a
64-bit no-op BPF_END both before the loop and on the backedge,
compute_header_scevs() and is_iv_at_header() treat r as congruent to
iv_reg. bpf_widen_scev_regs() and bpf_clamp_scev_regs() then intersect
r's scalar bounds with iv_range, causing the verifier to bound a register
holding a raw 64-bit kernel pointer to the small scalar range [1, 10] and
allowing out-of-bounds memory access.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111051341.2800252-1-alexei.starovoitov@gmail.com?part=20
next prev parent reply other threads:[~2026-11-11 5:57 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 5:13 [PATCH bpf-next v2 00/29] bpf: Find linked registers by scalar evolution, remove scalar ids Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 01/29] bpf: Keep the 32-bit range across a no-op sign extension Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 02/29] bpf: Model 32-bit shifts and divisions exactly in scalar evolution Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 03/29] bpf: Construct scalar evolution expressions without allocations Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 04/29] bpf: Don't join dead registers in scalar evolution Alexei Starovoitov
2026-11-11 8:27 ` bot+bpf-ci
2026-11-11 5:13 ` [PATCH bpf-next v2 05/29] bpf: Simplify scalar evolution expressions at construction Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 06/29] bpf: Give SSA names to the values that scalar evolution does not track Alexei Starovoitov
2026-11-11 8:27 ` bot+bpf-ci
2026-11-11 5:13 ` [PATCH bpf-next v2 07/29] bpf: Compute scalar evolution expressions for whole subprogs Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 08/29] bpf: Mark the attr argument of bpf_sys_bpf() as MEM_WRITE Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 09/29] bpf: Include older frames in a fill through an imprecise stack pointer Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 10/29] bpf: Detect a dead branch when a range and var_off don't overlap Alexei Starovoitov
2026-11-11 8:27 ` bot+bpf-ci
2026-11-11 5:13 ` [PATCH bpf-next v2 11/29] bpf: Don't treat half of a 64-bit spill as a 32-bit spill on big endian Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 12/29] bpf: Refine registers linked by scalar evolution at conditional jumps Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 13/29] bpf: Value number the phis of scalar evolution Alexei Starovoitov
2026-11-11 8:27 ` bot+bpf-ci
2026-11-11 5:13 ` [PATCH bpf-next v2 14/29] selftests/bpf: Test registers linked by " Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 15/29] selftests/bpf: Test sign extensions of a range and of a linked register Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 16/29] bpf: Recompute a pointer after the jump that bounds its index Alexei Starovoitov
2026-11-11 5:48 ` sashiko-bot
2026-11-11 5:13 ` [PATCH bpf-next v2 17/29] selftests/bpf: Test a pointer computed before its index is bounded Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 18/29] bpf: Promote memory behind a pointer to SCEV registers Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 19/29] selftests/bpf: Test the memory of a caller that a jump tests Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 20/29] bpf: Find a copy of an induction variable without scalar ids Alexei Starovoitov
2026-11-11 5:57 ` sashiko-bot [this message]
2026-11-11 5:13 ` [PATCH bpf-next v2 21/29] bpf: Compute scalar evolution expressions in irreducible loops Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 22/29] bpf: Remove sync_linked_regs(), refine by scalar evolution only Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 23/29] bpf: Recognize copies of a scalar by their ranges in flow_join_makes_up() Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 24/29] bpf: Stop assigning ids to scalars Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 25/29] bpf: Remove scalar ids from regsafe() Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 26/29] bpf: Remove scalar ids from the join of states Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 27/29] bpf: Remove scalar ids from the log and from bpf_verifier.h Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 28/29] bpf: Support sign-extended 32-bit linear scalar evolution Alexei Starovoitov
2026-11-11 5:13 ` [PATCH bpf-next v2 29/29] selftests/bpf: Test loops with a sign-extended 32-bit induction variable Alexei Starovoitov
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=sashiko-outbox-208372@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.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