Re: [PATCH bpf-next v2 2/5] bpf: track upper 32-bit register halves' liveness in compute_live_registers()

[email protected] Sat, 01 Aug 2026 01:35:08 +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:
- [High] Skipping zero-extension for 32-bit kfunc arguments causes ABI violations on architectures that require the caller to extend 32-bit parameters.
--

--- Patch [2]: [PATCH bpf-next v2 2/5] bpf: track upper 32-bit register halves' liveness in compute_live_registers() ---
commit 2a034896228b7579bf93bf8ae2024cee100ebcba
Author: Eduard Zingerman <[email protected]>

bpf: track upper 32-bit register halves' liveness in compute_live_registers()

This commit extends compute_live_registers() to track the upper and lower 
register halves' liveness separately. It updates compute_insn_live_regs() 
to track these bits and infers whether the upper half of a parameter 
register is used by a kfunc call based on its BTF type size.

> diff --git a/kernel/bpf/liveness.c b/kernel/bpf/liveness.c
> index ff1e68cc4bd1c..d0bd94c60fee2 100644
> --- a/kernel/bpf/liveness.c
> +++ b/kernel/bpf/liveness.c

[ ... ]

> +static u32 call_use_mask(struct bpf_verifier_env *env, struct bpf_insn *insn)
> +{
> +	u32 i, use, size, reg_params_num;
> +	struct bpf_call_summary cs;
> +	const struct btf_param *p;
> +	const struct btf_type *t;
> +
> +	if (!bpf_get_call_summary(env, insn, &cs))
> +		/* e.g. a bpf-to-bpf call, assume that calls use full 64-bit for each param */
> +		return mask_widen(ALL_CALLER_SAVED_REGS & ~BIT(BPF_REG_0));
> +
> +	if (cs.func_proto) {
> +		use = 0;
> +		p = btf_params(cs.func_proto);
> +		reg_params_num = min(btf_type_vlen(cs.func_proto), MAX_BPF_FUNC_REG_ARGS);
> +		for (i = 0; i < reg_params_num; i++) {
> +			t = btf_type_by_id(cs.btf, p[i].type);
> +			if (IS_ERR(btf_resolve_size(cs.btf, t, &size)))
> +				goto fallback;
> +			use |= size <= sizeof(u32) ? reg32_mask(i + 1) : reg64_mask(i + 1);

[Severity: High]
Does this break the C ABI on architectures that require the caller to
zero-extend or sign-extend 32-bit parameters passed in 64-bit registers?

By only marking the lower 32 bits as used for smaller parameters with
reg32_mask, the upper 32 bits are marked as dead before the kfunc call.
Consequently, the verifier computes zext_dst = false for the instruction
that previously defined the argument.

This causes the JIT to skip inserting a BPF_ZEXT_REG instruction to clear
the upper 32 bits on architectures where bpf_jit_needs_zext() is true,
such as s390x and PowerPC64.

If a BPF program computes a 32-bit value and passes it to a kfunc expecting
a 32-bit parameter, the kfunc might operate on garbage data in the upper
32 bits.

> +		}
> +		return use;
> +	}

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