Re: [PATCH bpf-next v3 3/5] bpf: infer zext_dst based on static register liveness analysis

[email protected] Sun, 02 Aug 2026 21:07:41 +0000
Newsgroups org.kernel.vger.bpf
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Missing zero-extension for BPF_ADDR_SPACE_CAST allows out-of-bounds arena access on architectures needing explicit zero-extension.
--

--- Patch [3]: [PATCH bpf-next v3 3/5] bpf: infer zext_dst based on static register liveness analysis ---
commit 740202f3328f4855ad10128ef188400086445fa9
Author: Eduard Zingerman <[email protected]>

bpf: infer zext_dst based on static register liveness analysis

This patch replaces dynamic subreg_def tracking with a static computation of 
zext_dst during register liveness analysis. The verifier now tracks the usage 
of upper and lower register halves separately to infer whether a 32-bit 
subregister definition requires explicit zero extension.

Link: https://lore.kernel.org/bpf/CAGKGUv=sOuqQtA1Ub-5JXfA4FPosJFYKAQE4B79cK+P1erxqtg@mail.gmail.com/

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 896bc5aaaaaff..e51cf5238f60a 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -15026,18 +14941,14 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
>  				if (insn->imm) {
>  					/* off == BPF_ADDR_SPACE_CAST */
>  					mark_reg_unknown(env, regs, insn->dst_reg);
> -					if (insn->imm == 1) { /* cast from as(1) to as(0) */
> +					if (insn->imm == 1) /* cast from as(1) to as(0) */
>  						dst_reg->type = PTR_TO_ARENA;
> -						/* PTR_TO_ARENA is 32-bit */
> -						dst_reg->subreg_def = env->insn_idx + 1;
> -					}

[Severity: Critical]
Does this missing zero-extension for BPF_ADDR_SPACE_CAST allow out-of-bounds
arena access on architectures needing explicit zero-extension?

The patch removed the dynamic dst_reg->subreg_def = env->insn_idx + 1
assignment here. Since a BPF_ADDR_SPACE_CAST instruction is encoded as
BPF_ALU64 | BPF_MOV | BPF_X, the new bpf_insn_def32() function returns -1,
which evaluates zext_dst to false in the static liveness analysis.

Because check_alu_op() handles the cast but does not manually set
aux->zext_dst = true (unlike how it was handled in adjust_reg_min_max_vals()),
the subsequent zero-extension insertion pass is skipped.

On architectures like s390x, wouldn't this leave uninitialized garbage in the
upper 32 bits, allowing arbitrary kernel memory read/writes when the JIT adds
this register to the 64-bit arena base?

>  				} else if (insn->off == 0) {
>  					/* case: R1 = R2
>  					 * copy register state to dest reg
>  					 */

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=3