Skip to content

Commit 2321a95

Browse files
S4CHAlexei Starovoitov
authored andcommitted
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: 6082b6c ("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>
1 parent ac72464 commit 2321a95

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

kernel/bpf/core.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,27 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from,
14221422
*to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd);
14231423
*to++ = BPF_STX_MEM(from->code, from->dst_reg, BPF_REG_AX, from->off);
14241424
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;
14251446
}
14261447
out:
14271448
return to - to_buff;

0 commit comments

Comments
 (0)