Skip to content

Commit 845c707

Browse files
Daniel Sneddongregkh
authored andcommitted
x86/bpf: Call branch history clearing sequence on exit
commit d4e89d212d401672e9cdfe825d947ee3a9fbe3f5 upstream. Classic BPF programs have been identified as potential vectors for intra-mode Branch Target Injection (BTI) attacks. Classic BPF programs can be run by unprivileged users. They allow unprivileged code to execute inside the kernel. Attackers can use unprivileged cBPF to craft branch history in kernel mode that can influence the target of indirect branches. Introduce a branch history buffer (BHB) clearing sequence during the JIT compilation of classic BPF programs. The clearing sequence is the same as is used in previous mitigations to protect syscalls. Since eBPF programs already have their own mitigations in place, only insert the call on classic programs that aren't run by privileged users. Signed-off-by: Daniel Sneddon <[email protected]> Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9fc1391 commit 845c707

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,29 @@ static void emit_nops(u8 **pprog, int len)
947947
#define RESTORE_TAIL_CALL_CNT(stack) \
948948
EMIT3_off32(0x48, 0x8B, 0x85, -round_up(stack, 8) - 8)
949949

950+
static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
951+
struct bpf_prog *bpf_prog)
952+
{
953+
u8 *prog = *pprog;
954+
u8 *func;
955+
956+
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
957+
/* The clearing sequence clobbers eax and ecx. */
958+
EMIT1(0x50); /* push rax */
959+
EMIT1(0x51); /* push rcx */
960+
ip += 2;
961+
962+
func = (u8 *)clear_bhb_loop;
963+
964+
if (emit_call(&prog, func, ip))
965+
return -EINVAL;
966+
EMIT1(0x59); /* pop rcx */
967+
EMIT1(0x58); /* pop rax */
968+
}
969+
*pprog = prog;
970+
return 0;
971+
}
972+
950973
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
951974
int oldproglen, struct jit_context *ctx, bool jmp_padding)
952975
{
@@ -1760,6 +1783,15 @@ st: if (is_imm8(insn->off))
17601783
seen_exit = true;
17611784
/* Update cleanup_addr */
17621785
ctx->cleanup_addr = proglen;
1786+
1787+
if (bpf_prog_was_classic(bpf_prog) &&
1788+
!capable(CAP_SYS_ADMIN)) {
1789+
u8 *ip = image + addrs[i - 1];
1790+
1791+
if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
1792+
return -EINVAL;
1793+
}
1794+
17631795
pop_callee_regs(&prog, callee_regs_used);
17641796
EMIT1(0xC9); /* leave */
17651797
emit_return(&prog, image + addrs[i - 1] + (prog - temp));

0 commit comments

Comments
 (0)