Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf, arm64: Fix off-by-one in check_imm signed range check

check_imm(bits, imm) is used in the arm64 BPF JIT to verify that
a branch displacement (in arm64 instruction units) fits into the
signed N-bit immediate field of a B, B.cond or CBZ/CBNZ encoding
before it is handed to the encoder. The macro currently tests for
(imm > 0 && imm >> bits) || (imm < 0 && ~imm >> bits) which admits
values in [-2^N, 2^N) — effectively a signed (N+1)-bit range. A
signed N-bit field only holds [-2^(N-1), 2^(N-1)), so the check
admits one extra bit of range on each side.

In particular, for check_imm19(), values in [2^18, 2^19) slip past
the check but do not fit into the 19-bit signed imm19 field of
B.cond. aarch64_insn_encode_immediate() then masks the raw value
into the 19-bit field, setting bit 18 (the sign bit) and flipping
a forward branch into a backward one. Same class of issue exists
for check_imm26() and the B/BL encoding. Shift by (bits - 1)
instead of bits so the actual signed N-bit range is enforced.

Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Link: https://lore.kernel.org/r/20260415121403.639619-2-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
1dd8be4e 48d83d94

+2 -2
+2 -2
arch/arm64/net/bpf_jit_comp.c
··· 35 35 #define ARENA_VM_START (MAX_BPF_JIT_REG + 5) 36 36 37 37 #define check_imm(bits, imm) do { \ 38 - if ((((imm) > 0) && ((imm) >> (bits))) || \ 39 - (((imm) < 0) && (~(imm) >> (bits)))) { \ 38 + if ((((imm) > 0) && ((imm) >> ((bits) - 1))) || \ 39 + (((imm) < 0) && (~(imm) >> ((bits) - 1)))) { \ 40 40 pr_info("[%2d] imm=%d(0x%x) out of range\n", \ 41 41 i, imm, imm); \ 42 42 return -EINVAL; \