[PATCH stable 6.12 1/4] bpf: Fix linked reg delta tracking when src_reg == dst_reg
Shung-Hsi Yu <[email protected]>
| Newsgroups | org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
From: Daniel Borkmann <[email protected]> commit d7f14173c0d5866c3cae759dee560ad1bed10d2e upstream. Consider the case of rX += rX where src_reg and dst_reg are pointers to the same bpf_reg_state in adjust_reg_min_max_vals(). The latter first modifies the dst_reg in-place, and later in the delta tracking, the subsequent is_reg_const(src_reg)/reg_const_value(src_reg) reads the post-{add,sub} value instead of the original source. This is problematic since it sets an incorrect delta, which sync_linked_regs() then propagates to linked registers, thus creating a verifier-vs-runtime mismatch. Fix it by just skipping this corner case. Fixes: 98d7ca374ba4 ("bpf: Track delta between "linked" registers.") Reported-by: STAR Labs SG <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]> [shung-hsi.yu: contextual difference due to commit 7a433e519364 ("bpf: Support negative offsets, BPF_SUB, and alu32 for linked register tracking") not backported. ] Signed-off-by: Shung-Hsi Yu <[email protected]> --- Checked that after this patchset is applied, no new test failure occurs[1] when compared to baseline[2] (which currently has some failures unrelated to this patchset). 1: https://github.com/kernel-patches/linux-stable/actions/runs/32108723314/ 2: https://github.com/kernel-patches/linux-stable/actions/runs/32061193394/ --- kernel/bpf/verifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 77183b436da5..eb84924799a4 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -14543,7 +14543,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, */ if (env->bpf_capable && BPF_OP(insn->code) == BPF_ADD && !alu32 && - dst_reg->id && is_reg_const(src_reg, false)) { + dst_reg->id && is_reg_const(src_reg, false) && + !(BPF_SRC(insn->code) == BPF_X && insn->src_reg == insn->dst_reg)) { u64 val = reg_const_value(src_reg, false); if ((dst_reg->id & BPF_ADD_CONST) || base-commit: 25c09b42358e73e1476e517b296edb6344f2e4bd -- 2.55.0