]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Reset register ID for BPF_END value tracking
authorYazhou Tang <tangyazhou518@outlook.com>
Wed, 4 Mar 2026 08:32:27 +0000 (16:32 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 10 Mar 2026 18:46:31 +0000 (11:46 -0700)
When a register undergoes a BPF_END (byte swap) operation, its scalar
value is mutated in-place. If this register previously shared a scalar ID
with another register (e.g., after an `r1 = r0` assignment), this tie must
be broken.

Currently, the verifier misses resetting `dst_reg->id` to 0 for BPF_END.
Consequently, if a conditional jump checks the swapped register, the
verifier incorrectly propagates the learned bounds to the linked register,
leading to false confidence in the linked register's value and potentially
allowing out-of-bounds memory accesses.

Fix this by explicitly resetting `dst_reg->id` to 0 in the BPF_END case
to break the scalar tie, similar to how BPF_NEG handles it via
`__mark_reg_known`.

Fixes: 9d2119984224 ("bpf: Add bitwise tracking for BPF_END")
Closes: https://lore.kernel.org/bpf/AMBPR06MB108683CFEB1CB8D9E02FC95ECF17EA@AMBPR06MB10868.eurprd06.prod.outlook.com/
Link: https://lore.kernel.org/bpf/4be25f7442a52244d0dd1abb47bc6750e57984c9.camel@gmail.com/
Reported-by: Guillaume Laporte <glapt.pro@outlook.com>
Co-developed-by: Tianci Cao <ziye@zju.edu.cn>
Signed-off-by: Tianci Cao <ziye@zju.edu.cn>
Co-developed-by: Shenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: Shenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: Yazhou Tang <tangyazhou518@outlook.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260304083228.142016-2-tangyazhou@zju.edu.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index 159b25f8269ddfd6f66edabbca06e3822e56a330..df22bfc572e240ceb0efba985d97d69dc761e9f6 100644 (file)
@@ -15910,6 +15910,13 @@ static void scalar_byte_swap(struct bpf_reg_state *dst_reg, struct bpf_insn *ins
        /* Apply bswap if alu64 or switch between big-endian and little-endian machines */
        bool need_bswap = alu64 || (to_le == is_big_endian);
 
+       /*
+        * If the register is mutated, manually reset its scalar ID to break
+        * any existing ties and avoid incorrect bounds propagation.
+        */
+       if (need_bswap || insn->imm == 16 || insn->imm == 32)
+               dst_reg->id = 0;
+
        if (need_bswap) {
                if (insn->imm == 16)
                        dst_reg->var_off = tnum_bswap16(dst_reg->var_off);