Skip to content

Commit d4e89d2

Browse files
Daniel Sneddonhansendc
authored andcommitted
x86/bpf: Call branch history clearing sequence on exit
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]>
1 parent 92a09c4 commit d4e89d2

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,30 @@ static void emit_priv_frame_ptr(u8 **pprog, void __percpu *priv_frame_ptr)
15021502
#define PRIV_STACK_GUARD_SZ 8
15031503
#define PRIV_STACK_GUARD_VAL 0xEB9F12345678eb9fULL
15041504

1505+
static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
1506+
struct bpf_prog *bpf_prog)
1507+
{
1508+
u8 *prog = *pprog;
1509+
u8 *func;
1510+
1511+
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
1512+
/* The clearing sequence clobbers eax and ecx. */
1513+
EMIT1(0x50); /* push rax */
1514+
EMIT1(0x51); /* push rcx */
1515+
ip += 2;
1516+
1517+
func = (u8 *)clear_bhb_loop;
1518+
ip += x86_call_depth_emit_accounting(&prog, func, ip);
1519+
1520+
if (emit_call(&prog, func, ip))
1521+
return -EINVAL;
1522+
EMIT1(0x59); /* pop rcx */
1523+
EMIT1(0x58); /* pop rax */
1524+
}
1525+
*pprog = prog;
1526+
return 0;
1527+
}
1528+
15051529
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
15061530
int oldproglen, struct jit_context *ctx, bool jmp_padding)
15071531
{
@@ -2544,6 +2568,13 @@ st: if (is_imm8(insn->off))
25442568
seen_exit = true;
25452569
/* Update cleanup_addr */
25462570
ctx->cleanup_addr = proglen;
2571+
if (bpf_prog_was_classic(bpf_prog) &&
2572+
!capable(CAP_SYS_ADMIN)) {
2573+
u8 *ip = image + addrs[i - 1];
2574+
2575+
if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
2576+
return -EINVAL;
2577+
}
25472578
if (bpf_prog->aux->exception_boundary) {
25482579
pop_callee_regs(&prog, all_callee_regs_used);
25492580
pop_r12(&prog);

0 commit comments

Comments
 (0)