Commit a3125bc0 authored by Yazhou Tang's avatar Yazhou Tang Committed by Alexei Starovoitov
Browse files

bpf: Reset register ID for BPF_END value tracking

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: 9d211998 ("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: default avatarGuillaume Laporte <glapt.pro@outlook.com>
Co-developed-by: default avatarTianci Cao <ziye@zju.edu.cn>
Signed-off-by: default avatarTianci Cao <ziye@zju.edu.cn>
Co-developed-by: default avatarShenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: default avatarShenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: default avatarYazhou Tang <tangyazhou518@outlook.com>
Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260304083228.142016-2-tangyazhou@zju.edu.cn


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 1f318b96
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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);