Skip to content

Commit 80b28a6

Browse files
S4CHKernel Patches Daemon
authored andcommitted
bpf: fix constant blinding bypass 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>
1 parent 80bf62c commit 80b28a6

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

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)