mirror of https://github.com/torvalds/linux.git
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 <daniel.sneddon@linux.intel.com> Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com>
This commit is contained in:
parent
92a09c4746
commit
d4e89d212d
|
|
@ -1502,6 +1502,30 @@ static void emit_priv_frame_ptr(u8 **pprog, void __percpu *priv_frame_ptr)
|
|||
#define PRIV_STACK_GUARD_SZ 8
|
||||
#define PRIV_STACK_GUARD_VAL 0xEB9F12345678eb9fULL
|
||||
|
||||
static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
|
||||
struct bpf_prog *bpf_prog)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
u8 *func;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
|
||||
/* The clearing sequence clobbers eax and ecx. */
|
||||
EMIT1(0x50); /* push rax */
|
||||
EMIT1(0x51); /* push rcx */
|
||||
ip += 2;
|
||||
|
||||
func = (u8 *)clear_bhb_loop;
|
||||
ip += x86_call_depth_emit_accounting(&prog, func, ip);
|
||||
|
||||
if (emit_call(&prog, func, ip))
|
||||
return -EINVAL;
|
||||
EMIT1(0x59); /* pop rcx */
|
||||
EMIT1(0x58); /* pop rax */
|
||||
}
|
||||
*pprog = prog;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
|
||||
int oldproglen, struct jit_context *ctx, bool jmp_padding)
|
||||
{
|
||||
|
|
@ -2544,6 +2568,13 @@ st: if (is_imm8(insn->off))
|
|||
seen_exit = true;
|
||||
/* Update cleanup_addr */
|
||||
ctx->cleanup_addr = proglen;
|
||||
if (bpf_prog_was_classic(bpf_prog) &&
|
||||
!capable(CAP_SYS_ADMIN)) {
|
||||
u8 *ip = image + addrs[i - 1];
|
||||
|
||||
if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (bpf_prog->aux->exception_boundary) {
|
||||
pop_callee_regs(&prog, all_callee_regs_used);
|
||||
pop_r12(&prog);
|
||||
|
|
|
|||
Loading…
Reference in New Issue