BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Eduard Zingerman" <eddyz87@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next 24/36] bpf: compute scalar evolution expressions for loops
Date: Sat, 26 Sep 2026 14:38:16 +0000	[thread overview]
Message-ID: <20260926143816.D6F581F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260926-scev-minimal-rebase-v1-24-c8e5ab5ba79f@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] bpf: NULL pointer dereference in compute_insn_scevs() for loops with exits_overflow
- [Medium] bpf: Incorrect SCEV modeling of BPF_END no-op conversions preserves truncated bits
--

commit 3c85c59367498a632c83889db787693adfac36e5
Author: Eduard Zingerman <eddyz87@gmail.com>
Subject: bpf: compute scalar evolution expressions for loops

This patch assigns algebraic expressions to loop variables (registers and
stack spills) to describe how their values evolve across iterations. The
analysis proceeds in two phases: computing expressions for one symbolic
iteration and converting backedge updates to recurrences.

> diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c
> new file mode 100644
> index 0000000000000..396b0c776dfae
> --- /dev/null
> +++ b/kernel/bpf/scev.c
[ ... ]
> @@ -713,29 +713,25 @@ static int transfer(struct bpf_verifier_env *env, struct env *e, int idx)
[ ... ]
> +		case BPF_END:
> +			switch (insn->imm) {
> +			case 16: op = BSWAP16; break;
> +			case 32: op = BSWAP32; break;
> +			case 64: op = BSWAP64; break;
> +			default:
> +				goto mark_dst_unknown;
> +			}
> +
> +			if (class == BPF_ALU && x_or_k == BPF_TO_LE && insn->off == 0 && little_endian)
> +				op = 0; /* little-endian to little-endian is noop */

[Severity: Medium]
Can this skip the required 16-bit truncation semantics?

When a BPF_END instruction is a 16-bit endianness conversion (imm == 16)
and acts as a no-op on the current architecture, op is set to 0.

Because op is 0, the explicit truncation operation (like ZEXT16) is skipped
below. Only ZEXT32 is applied to the register:

kernel/bpf/scev.c:transfer() {
    id = reg2expr[dst];
    if (op)
        id = expr1(scev, op, reg2expr[dst]);

    if (class == BPF_ALU)
        id = expr1(scev, ZEXT32, id);
    ...
}

The verifier and hardware will still truncate the register to 16 bits,
zeroing bits 16-63. By skipping this in the algebraic model, does it
incorrectly preserve bits 16-31 of the original register?

> +			else if (class == BPF_ALU && x_or_k == BPF_TO_BE && insn->off == 0 && !little_endian)
> +				op = 0; /* big-endian to big-endian is noop */
> +			else if (class == BPF_ALU64 && x_or_k == 0 && insn->off == 0)
> +				/* always swap */;
> +			else
> +				goto mark_dst_unknown;
> +
> +			id = reg2expr[dst];
> +			if (op)
> +				id = expr1(scev, op, reg2expr[dst]);
> +
> +			if (class == BPF_ALU)
> +				id = expr1(scev, ZEXT32, id);
> +
> +			return replace_reg(scev, e, dst, id);
[ ... ]
> @@ -1172,13 +1172,13 @@ static void mark_latches(struct bpf_verifier_env *env)
> +	for (i = 0; i < len; i++) {
> +		loop = aux[i].loop;
> +		if (!loop)
> +			continue;
> +		aux[i].need_scev = true;
> +		if (loop->irreducible)
> +			continue;

[Severity: High]
Does this code result in a NULL pointer dereference when a loop has an
exits_overflow condition?

Loops with exits_overflow are not skipped here (unlike irreducible loops),
so their latches are marked with aux[latch].need_scev = true.

However, compute_scev_for_loop() bails out early for exits_overflow loops
and does not allocate a loop environment for the latch:

kernel/bpf/scev.c:compute_scev_for_loop() {
    if (cur_loop->irreducible || cur_loop->exits_overflow) {
        header_env = get_loop_env(scev, cur_header, cur_header);
        ...
        return 0;
    }
    ...
}

Later, when bpf_compute_scev() visits the latch, it calls
compute_insn_scevs(), passing the result of find_loop_env(). Since the
environment was never created, find_loop_env() returns NULL.

This results in einsn being NULL in compute_insn_scevs():

kernel/bpf/scev.c:compute_insn_scevs() {
    ...
    for (reg = 0; reg < REGS_NUM; reg++) {
        id = einsn->reg2expr[reg];
}

Should exits_overflow loops be skipped here similarly to irreducible loops?

> +		for (j = 0; j < loop->backedges_cnt; j++) {
> +			latch = loop->backedges[j].latch;
> +			if (latch >= 0)
> +				aux[latch].need_scev = true;
> +		}
> +	}
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260926-scev-minimal-rebase-v1-0-c8e5ab5ba79f@gmail.com?part=24

  reply	other threads:[~2026-09-26 14:38 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-26 14:19 [PATCH bpf-next 00/36] bpf: use scalar evolution to widen bounded loops Eduard Zingerman
2026-09-26 14:19 ` [PATCH bpf-next 01/36] bpf: track may_write flags in liveness Eduard Zingerman
2026-09-26 15:51   ` Alexei Starovoitov
2026-09-27  8:43     ` Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 02/36] bpf: summarize may write stack slots in insn_aux_data Eduard Zingerman
2026-09-26 15:51   ` Alexei Starovoitov
2026-09-29 20:12     ` Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 03/36] bpf: summarize live " Eduard Zingerman
2026-09-26 14:33   ` sashiko-bot
2026-09-27 20:26   ` bot+bpf-ci
2026-09-29 18:16     ` Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 04/36] bpf: summarize regs that may hold a frame pointer " Eduard Zingerman
2026-09-27 20:27   ` bot+bpf-ci
2026-09-29 20:21     ` Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 05/36] bpf: record write effects for atomic operations in liveness.c Eduard Zingerman
2026-09-27 20:27   ` bot+bpf-ci
2026-09-29 20:26     ` Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 06/36] bpf: add tnum_alignment() Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 07/36] bpf: add cnum{32,64}_union() Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 08/36] bpf: add cnum64_intersect_linear() Eduard Zingerman
2026-09-26 14:34   ` sashiko-bot
2026-09-29 21:46     ` Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 09/36] bpf: add bpf_set_reg_range() Eduard Zingerman
2026-09-26 14:36   ` sashiko-bot
2026-09-26 14:20 ` [PATCH bpf-next 10/36] bpf: add bpf_mark_reg_known_scalar() Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 11/36] bpf: add bpf_reg_union() Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci
2026-09-30  0:09     ` Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 12/36] bpf: expose comparison opcode transformations Eduard Zingerman
2026-09-27 20:26   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 13/36] bpf: allow subrange relations for PTR_TO_STACK in regsafe() Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 14/36] bpf: representation for intervals with steps Eduard Zingerman
2026-09-26 14:35   ` sashiko-bot
2026-09-26 14:20 ` [PATCH bpf-next 15/36] bpf: varying offset access support for PTR_TO_BTF_ID pointers Eduard Zingerman
2026-09-26 14:37   ` sashiko-bot
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 16/36] bpf: save DFS postorder numbers for program instructions Eduard Zingerman
2026-09-26 14:31   ` sashiko-bot
2026-09-26 14:20 ` [PATCH bpf-next 17/36] bpf: move the live-register and SCC printout to a standalone function Eduard Zingerman
2026-09-27 20:26   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 18/36] bpf: compute immediate dominators Eduard Zingerman
2026-09-26 15:54   ` Alexei Starovoitov
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 19/36] bpf: compute loop hierarchy Eduard Zingerman
2026-09-27 20:43   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 20/36] bpf: add a min-heap for ordered analysis worklists Eduard Zingerman
2026-09-27 20:26   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 21/36] bpf: record basic-block ends in insn_aux_data Eduard Zingerman
2026-09-27 20:26   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 22/36] bpf: add bpf_split_cur_state() Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 23/36] bpf: allow precision backtracking between overlapping checkpoints Eduard Zingerman
2026-09-27 20:27   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 24/36] bpf: compute scalar evolution expressions for loops Eduard Zingerman
2026-09-26 14:38   ` sashiko-bot [this message]
2026-09-27 20:43   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 25/36] bpf: use SCEV to widen bounded loops Eduard Zingerman
2026-09-26 14:42   ` sashiko-bot
2026-09-27 20:43   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 26/36] bpf: avoid widening registers that hinder exact stack-slot tracking Eduard Zingerman
2026-09-26 14:46   ` sashiko-bot
2026-09-27 20:43   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 27/36] selftests/bpf: __msg_next tag for matching messages on consecutive lines Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 28/36] selftests/bpf: test for stack-pointer subrange pruning Eduard Zingerman
2026-09-26 14:32   ` sashiko-bot
2026-09-27 20:26   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 29/36] selftests/bpf: tests for may_write stack-liveness tracking Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 30/36] selftests/bpf: tests for may_def marks of atomic RMW operations Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 31/36] selftests/bpf: tests for register base/step arithmetic Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 32/36] selftests/bpf: tests for register base/step state pruning Eduard Zingerman
2026-09-27 20:27   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 33/36] selftests/bpf: tests for varying offset access to PTR_TO_BTF_ID Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 34/36] selftests/bpf: tests for loop hierarchy computation Eduard Zingerman
2026-09-26 14:20 ` [PATCH bpf-next 35/36] selftests/bpf: tests for immediate dominator computation Eduard Zingerman
2026-09-27 20:27   ` bot+bpf-ci
2026-09-26 14:20 ` [PATCH bpf-next 36/36] selftests/bpf: cover SCEV analysis and loop widening Eduard Zingerman
2026-09-27 20:42   ` bot+bpf-ci

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=20260926143816.D6F581F00893@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