From: Eduard Zingerman <eddyz87@gmail.com>
To: sashiko-reviews@lists.linux.dev
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next 3/5] bpf: infer zext_dst based on static register liveness analysis
Date: Fri, 31 Jul 2026 14:17:40 -0700 [thread overview]
Message-ID: <bfa89ff4ec80943ffa5567f90779221ff82fa16c.camel@gmail.com> (raw)
In-Reply-To: <20260731192635.8B8111F00AC4@smtp.kernel.org>
On Fri, 2026-07-31 at 19:26 +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Critical] Incorrect static liveness tracking for 64-bit conditional jumps leads to missing zero-extensions (`zext_dst`), resulting in verifier/runtime state divergence and potential privilege escalation.
> --
>
> --- Patch [3]: [PATCH bpf-next 3/5] bpf: infer zext_dst based on static register liveness analysis ---
> commit ab8592d6a434dbfed0cbb0bd067d9032b308db8d
> Author: Eduard Zingerman <eddyz87@gmail.com>
>
> bpf: infer zext_dst based on static register liveness analysis
>
> This commit replaces the dynamic subreg_def based zero-extension
> tracking with static liveness analysis to correctly infer zext_dst
> and prevent missing zero-extensions on architectures like s390x.
>
> Link: https://lore.kernel.org/bpf/CAGKGUv=sOuqQtA1Ub-5JXfA4FPosJFYKAQE4B79cK+P1erxqtg@mail.gmail.com/
>
> > diff --git a/kernel/bpf/liveness.c b/kernel/bpf/liveness.c
> > index c996b8a03e792..ea002550671a8 100644
> > --- a/kernel/bpf/liveness.c
> > +++ b/kernel/bpf/liveness.c
> > @@ -2317,9 +2318,18 @@ int bpf_compute_live_registers(struct bpf_verifier_env *env)
> > }
> >
> > for (i = 0; i < insn_cnt; ++i) {
> > + int def32 = bpf_insn_def32(&insns[i]);
> > + u32 out = state[i].out;
> > u32 in = state[i].in;
> >
> > insn_aux[i].live_regs_before = mask_lo(in) | mask_hi(in);
> > + /*
> > + * On architectures where 32-bit operations do not reset upper halves
> > + * of the registers, the verifier needs to zero extend a destination
> > + * register if an instruction defines a 32-bit subregister and the
> > + * upper half of that register is alive after the instruction.
> > + */
> > + insn_aux[i].zext_dst = def32 >= 0 && (mask_hi(out) & BIT(def32));
>
> [Severity: Critical]
> Does this code correctly evaluate liveness for 64-bit conditional jumps?
>
> The new zext_dst logic relies on mask_hi(out) accurately reflecting if the
> upper half of a register is alive.
>
> However, looking at compute_insn_live_regs() in kernel/bpf/liveness.c for
> conditional jumps:
>
> const u8 class = BPF_CLASS(insn->code);
> const u8 code = BPF_OP(insn->code);
> ...
> case BPF_JMP:
> case BPF_JMP32:
> switch (code) {
> ...
> default:
> def = 0;
> if (BPF_SRC(insn->code) == BPF_K)
> use = dst;
> else
> use = dst | (code == BPF_JMP32 ? src : src32);
> }
>
> Can the code variable ever equal BPF_JMP32?
>
> BPF_OP() extracts the operation code (which is a multiple of 16), while
> BPF_JMP32 is a class (0x06). This means the check code == BPF_JMP32 evaluates
> to false, and the source register usage always falls back to src32, even for
> 64-bit jumps (BPF_JMP).
>
> If a 32-bit operation defines a register, and it is followed by a 64-bit
> conditional jump using that register as a source with no other uses of the
> upper 32 bits, the upper half won't be marked as alive.
>
> As a result, zext_dst wouldn't be set, which could lead to the JIT skipping
> the mandatory zero extension. This would cause the 64-bit jump to compare
> against uninitialized garbage in the upper bits, potentially allowing
> out-of-bounds access.
>
> Should this check use class == BPF_JMP32 instead?
>
> > }
This is the same (real) issue as reported for the previous patch.
next prev parent reply other threads:[~2026-07-31 21:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 19:07 [PATCH bpf-next 0/5] bpf: infer zext_dst based on static register liveness analysis Eduard Zingerman
2026-07-31 19:07 ` [PATCH bpf-next 1/5] bpf: do not print a newline after disassembly in bpf_verbose_insn() Eduard Zingerman
2026-07-31 20:24 ` bot+bpf-ci
2026-07-31 21:12 ` Eduard Zingerman
2026-07-31 19:07 ` [PATCH bpf-next 2/5] bpf: track upper 32-bit register halves' liveness in compute_live_registers() Eduard Zingerman
2026-07-31 19:18 ` sashiko-bot
2026-07-31 21:16 ` Eduard Zingerman
2026-07-31 19:07 ` [PATCH bpf-next 3/5] bpf: infer zext_dst based on static register liveness analysis Eduard Zingerman
2026-07-31 19:26 ` sashiko-bot
2026-07-31 21:17 ` Eduard Zingerman [this message]
2026-07-31 19:07 ` [PATCH bpf-next 4/5] bpf: simplify the bpf_is_reg64() signature Eduard Zingerman
2026-07-31 19:18 ` sashiko-bot
2026-07-31 20:09 ` bot+bpf-ci
2026-07-31 19:07 ` [PATCH bpf-next 5/5] selftests/bpf: verify zext_dst annotations for various instructions Eduard Zingerman
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=bfa89ff4ec80943ffa5567f90779221ff82fa16c.camel@gmail.com \
--to=eddyz87@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.