[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.