From: sashiko-bot@kernel.org
To: "Eduard Zingerman" <eddyz87@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 28/43] bpf: compute scalar evolution expressions for loops
Date: Sun, 04 Oct 2026 14:00:00 +0000 [thread overview]
Message-ID: <20261004140000.E54D51F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20261004-scev-minimal-rebase-v2-28-f6254e29fdf2@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] bpf: SCEV analysis overwrites initial state, bypassing bounds checks on early exits
- [High] bpf: NULL pointer dereference in compute_insn_scevs for irreducible nested loops
- [Medium] bpf: log_scevs incorrectly rejects valid programs with nested latches under BPF_LOG_LEVEL2
--
commit 2d2f1f9c2cfacacbaf91e31cf373b1ae40a400ea
Author: Eduard Zingerman <eddyz87@gmail.com>
bpf: compute scalar evolution expressions for loops
This commit assigns algebraic expressions to loop variables to describe how
their values evolve across iterations without unrolling the loops. The analysis
proceeds in two phases, analyzing innermost loops first and treating nested
loops as opaque operations.
> diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c
> new file mode 100644
> index 0000000000000..9ef28e0d8d481
> --- /dev/null
> +++ b/kernel/bpf/scev.c
[ ... ]
> +static struct env *get_loop_env(struct scev *scev, int loop_header, int insn_idx)
> +{
[ ... ]
> + e->empty = true;
> + tmp->entries[cnt].loop_header = loop_header;
> + tmp->entries[cnt].env = e;
> + tmp->cnt = cnt + 1;
> + scev->envs[insn_idx] = tmp;
> + return e;
> +}
[ ... ]
> +static int setup_initial_loop_env(struct bpf_verifier_env *env, struct env *e, int insn_idx)
> +{
> + struct scev *scev = env->scev;
> + int i, err;
> +
> + for (i = 0; i < REGS_NUM; i++) {
> + err = replace_reg(scev, e, i, expr1(scev, REG, i));
> + if (err)
> + return err;
> + }
> + return 0;
> +}
[Severity: Critical]
Could this leave the loop environment marked as empty even after it has been
populated with the initial register state?
When get_loop_env() initializes the environment, it sets e->empty to true.
Since setup_initial_loop_env() does not set e->empty to false after filling
the registers, a subsequent call to join() on the backedge might completely
overwrite this initial state:
if (acc->empty) {
memcpy(acc, cur, sizeof(*acc));
acc->empty = false;
return 0;
}
If the loop exits on the first iteration, could the verifier mistakenly
assume a constant from the backedge instead of the actual entry value,
potentially bypassing bounds checks?
[ ... ]
> +static int compute_scev_for_loop(struct bpf_verifier_env *env, int cur_header)
> +{
[ ... ]
> + /*
> + * For irreducible loops, and for loops nesting a loop with a truncated
> + * exit list, just assume that everything is clobbered for now.
> + */
> + if (!can_compute_loop_scev(cur_loop)) {
> + header_env = get_loop_env(scev, cur_header, cur_header);
> + if (!header_env)
> + return -ENOMEM;
> + /* The freshly allocated environment has all expressions unknown. */
> + header_env->empty = false;
> + return 0;
> + }
[ ... ]
> +static int compute_insn_scevs(struct bpf_verifier_env *env, struct env *eheader, struct env *einsn)
> +{
> + struct scev *scev = env->scev;
> + int id, reg;
> +
> + for (reg = 0; reg < REGS_NUM; reg++) {
> + id = einsn->reg2expr[reg];
[Severity: High]
Is it possible for einsn to be NULL here?
If a reducible outer loop has an exit instruction that is physically located
inside a nested irreducible loop, compute_scev_for_loop() will skip
allocating body environments for the inner loop.
When bpf_compute_scev() iterates over instructions and calls find_loop_env()
for this instruction, it might return NULL. This would result in passing a
NULL pointer into compute_insn_scevs(), leading to a dereference here.
> + id = transform_expr_once(scev, 0, id, eheader->reg2scev, instantiate_header_scevs);
> + if (id < 0)
> + return id;
[ ... ]
> +static int log_scevs(struct bpf_verifier_env *env)
> +{
[ ... ]
> + if (!can_compute_loop_scev(loop))
> + continue;
> + for (j = 0; j < loop->backedges_cnt; j++) {
> + latch = loop->backedges[j].latch;
> + if (latch < 0)
> + continue;
> + bpf_log(log, " scev at latch %d:\n", latch);
> + latch_env = find_loop_env(scev, i, latch);
> + if (verifier_bug_if(!latch_env, env, "i=%d, latch=%d", i, latch))
> + return -EFAULT;
[Severity: Medium]
Could this trigger a verifier bug for valid programs when log level 2 is
enabled?
If an outer loop's latch is located inside a nested loop, its environment
might not be allocated since the nested loop's body is skipped during
evaluation. If so, find_loop_env() will return NULL, causing this check to
fail and abort verification for otherwise valid code.
> + print_env(env, latch_env, latch, PRINT_SCEV);
> + }
> + }
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261004-scev-minimal-rebase-v2-0-f6254e29fdf2@gmail.com?part=28
next prev parent reply other threads:[~2026-10-04 14:00 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-04 13:37 [PATCH bpf-next v2 00/43] bpf: use scalar evolution to widen bounded loops Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 01/43] bpf: represent stack access effects with arg_access_info Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:37 ` [PATCH bpf-next v2 02/43] bpf: describe helper stack accesses " Eduard Zingerman
2026-10-04 14:02 ` sashiko-bot
2026-10-04 13:37 ` [PATCH bpf-next v2 03/43] bpf: describe kfunc " Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 04/43] bpf: track may_write flags in liveness Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 05/43] bpf: summarize may write stack slots in insn_aux_data Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 06/43] bpf: summarize live " Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 07/43] bpf: summarize regs that may hold a frame pointer " Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 08/43] bpf: record write effects for atomic operations in liveness.c Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 09/43] bpf: add tnum_alignment() Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 10/43] bpf: add cnum{32,64}_union() Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 11/43] bpf: add cnum64_intersect_linear() Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 12/43] bpf: expose comparison opcode transformations Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:37 ` [PATCH bpf-next v2 13/43] bpf: allow subrange relations for PTR_TO_STACK in regsafe() Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 14/43] bpf: representation for intervals with steps Eduard Zingerman
2026-10-04 14:02 ` sashiko-bot
2026-10-04 14:40 ` bot+bpf-ci
2026-10-04 13:37 ` [PATCH bpf-next v2 15/43] bpf: varying offset access support for PTR_TO_BTF_ID pointers Eduard Zingerman
2026-10-04 15:11 ` bot+bpf-ci
2026-10-04 13:37 ` [PATCH bpf-next v2 16/43] bpf: save DFS postorder numbers for program instructions Eduard Zingerman
2026-10-04 13:37 ` [PATCH bpf-next v2 17/43] bpf: move the live-register and SCC printout to a standalone function Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 18/43] bpf: compute immediate dominators Eduard Zingerman
2026-10-04 13:50 ` sashiko-bot
2026-10-04 13:38 ` [PATCH bpf-next v2 19/43] bpf: compute loop hierarchy Eduard Zingerman
2026-10-04 14:40 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 20/43] bpf: add bpf_set_reg_range() Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 21/43] bpf: add bpf_mark_reg_known_scalar() Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 22/43] bpf: add bpf_reg_union() Eduard Zingerman
2026-10-04 13:59 ` sashiko-bot
2026-10-04 13:38 ` [PATCH bpf-next v2 23/43] bpf: add a min-heap for ordered analysis worklists Eduard Zingerman
2026-10-04 13:47 ` sashiko-bot
2026-10-06 16:53 ` Alexei Starovoitov
2026-10-04 13:38 ` [PATCH bpf-next v2 24/43] bpf: record basic-block ends in insn_aux_data Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 25/43] bpf: add bpf_split_cur_state() Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 26/43] bpf: add bpf_same_memory_origin() Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 27/43] bpf: allow precision backtracking between overlapping checkpoints Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 28/43] bpf: compute scalar evolution expressions for loops Eduard Zingerman
2026-10-04 14:00 ` sashiko-bot [this message]
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 29/43] bpf: use SCEV to widen bounded loops Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 30/43] bpf: avoid widening registers that hinder exact stack-slot tracking Eduard Zingerman
2026-10-04 14:02 ` sashiko-bot
2026-10-04 13:38 ` [PATCH bpf-next v2 31/43] bpf: bpf_func_state size optimization Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 32/43] selftests/bpf: __msg_next tag for matching messages on consecutive lines Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 33/43] selftests/bpf: bound UNIX socket path loops by sun_path size Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 34/43] selftests/bpf: test for stack-pointer subrange pruning Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 35/43] selftests/bpf: tests for may_write stack-liveness tracking Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 36/43] selftests/bpf: tests for may_def marks of atomic RMW operations Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 37/43] selftests/bpf: tests for map special cases in bpf_helper_stack_access_bytes() Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 38/43] selftests/bpf: tests for register base/step arithmetic Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 39/43] selftests/bpf: tests for register base/step state pruning Eduard Zingerman
2026-10-04 13:54 ` sashiko-bot
2026-10-04 13:38 ` [PATCH bpf-next v2 40/43] selftests/bpf: tests for varying offset access to PTR_TO_BTF_ID Eduard Zingerman
2026-10-04 13:38 ` [PATCH bpf-next v2 41/43] selftests/bpf: tests for loop hierarchy computation Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 42/43] selftests/bpf: tests for immediate dominator computation Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 13:38 ` [PATCH bpf-next v2 43/43] selftests/bpf: tests for SCEV analysis and loop widening Eduard Zingerman
2026-10-04 14:24 ` bot+bpf-ci
2026-10-04 20:04 ` [syzbot ci] Re: bpf: use scalar evolution to widen bounded loops syzbot ci
2026-10-06 16:40 ` [PATCH bpf-next v2 00/43] " patchwork-bot+netdevbpf
2026-10-06 16:45 ` 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=20261004140000.E54D51F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=eddyz87@gmail.com \
--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