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: Fix constant blinding for PROBE_MEM32 stores

BPF_ST | BPF_PROBE_MEM32 immediate stores are not handled by
bpf_jit_blind_insn(), allowing user-controlled 32-bit immediates to
survive unblinded into JIT-compiled native code when bpf_jit_harden >= 1.

The root cause is that convert_ctx_accesses() rewrites BPF_ST|BPF_MEM
to BPF_ST|BPF_PROBE_MEM32 for arena pointer stores during verification,
before bpf_jit_blind_constants() runs during JIT compilation. The
blinding switch only matches BPF_ST|BPF_MEM (mode 0x60), not
BPF_ST|BPF_PROBE_MEM32 (mode 0xa0). The instruction falls through
unblinded.

Add BPF_ST|BPF_PROBE_MEM32 cases to bpf_jit_blind_insn() alongside the
existing BPF_ST|BPF_MEM cases. The blinding transformation is identical:
load the blinded immediate into BPF_REG_AX via mov+xor, then convert
the immediate store to a register store (BPF_STX).

The rewritten STX instruction must preserve the BPF_PROBE_MEM32 mode so
the architecture JIT emits the correct arena addressing (R12-based on
x86-64). Cannot use the BPF_STX_MEM() macro here because it hardcodes
BPF_MEM mode; construct the instruction directly instead.

Fixes: 6082b6c328b5 ("bpf: Recognize addr_space_cast instruction in the verifier.")
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: Sachin Kumar <xcyfun@protonmail.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/Y6IT5VvNRchPBLI5D7JZHBzZrU9rb0ycRJPJzJSXGj7kJlX8RJwZFSM2YZjcDxoQKABkxt1T8Os2gi23PYyFuQe6KkZGWVyfz8K5afdy9ak=@protonmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Sachin Kumar and committed by
Alexei Starovoitov
2321a959 ac72464b

+21
+21
kernel/bpf/core.c
··· 1422 1422 *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); 1423 1423 *to++ = BPF_STX_MEM(from->code, from->dst_reg, BPF_REG_AX, from->off); 1424 1424 break; 1425 + 1426 + case BPF_ST | BPF_PROBE_MEM32 | BPF_DW: 1427 + case BPF_ST | BPF_PROBE_MEM32 | BPF_W: 1428 + case BPF_ST | BPF_PROBE_MEM32 | BPF_H: 1429 + case BPF_ST | BPF_PROBE_MEM32 | BPF_B: 1430 + *to++ = BPF_ALU64_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ 1431 + from->imm); 1432 + *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); 1433 + /* 1434 + * Cannot use BPF_STX_MEM() macro here as it 1435 + * hardcodes BPF_MEM mode, losing PROBE_MEM32 1436 + * and breaking arena addressing in the JIT. 1437 + */ 1438 + *to++ = (struct bpf_insn) { 1439 + .code = BPF_STX | BPF_PROBE_MEM32 | 1440 + BPF_SIZE(from->code), 1441 + .dst_reg = from->dst_reg, 1442 + .src_reg = BPF_REG_AX, 1443 + .off = from->off, 1444 + }; 1445 + break; 1425 1446 } 1426 1447 out: 1427 1448 return to - to_buff;