From 1538f8cb209f93ed99ddae606a02707e3bdd9dfc Mon Sep 17 00:00:00 2001 From: guenther Date: Mon, 31 Jul 2023 04:01:07 +0000 Subject: [PATCH] On CPUs with eIBRS ("enhanced Indirect Branch Restricted Speculation") or IBT enabled the kernel, the hardware should the attacks which retpolines were created to prevent. In those cases, retpolines should be a net negative for security as they are an indirect branch gadget. They're also slower. * use -mretpoline-external-thunk to give us control of the code used for indirect branches * default to using a retpoline as before, but marks it and the other ASM kernel retpolines for code patching * if the CPU has eIBRS, then enable it * if the CPU has eIBRS *or* IBT, then codepatch the three different retpolines to just indirect jumps make clean && make config required after this ok kettenis@ --- sys/arch/amd64/amd64/cpu.c | 38 +++++++++++++++++++++++++----- sys/arch/amd64/amd64/locore.S | 11 ++++++++- sys/arch/amd64/amd64/vector.S | 10 +++++++- sys/arch/amd64/conf/Makefile.amd64 | 4 ++-- sys/arch/amd64/include/codepatch.h | 5 +++- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c index 542d961d050..60220bff4f5 100644 --- a/sys/arch/amd64/amd64/cpu.c +++ b/sys/arch/amd64/amd64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.174 2023/07/28 06:36:16 guenther Exp $ */ +/* $OpenBSD: cpu.c,v 1.175 2023/07/31 04:01:07 guenther Exp $ */ /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */ /*- @@ -187,11 +187,7 @@ replacemeltdown(void) { static int replacedone = 0; struct cpu_info *ci = &cpu_info_primary; - int swapgs_vuln = 0, s; - - if (replacedone) - return; - replacedone = 1; + int swapgs_vuln = 0, ibrs = 0, s; if (strcmp(cpu_vendor, "GenuineIntel") == 0) { int family = ci->ci_family; @@ -208,9 +204,39 @@ replacemeltdown(void) /* KnightsLanding */ swapgs_vuln = 0; } + if ((ci->ci_feature_sefflags_edx & SEFF0EDX_ARCH_CAP) && + (rdmsr(MSR_ARCH_CAPABILITIES) & ARCH_CAP_IBRS_ALL)) { + ibrs = 2; + } else if (ci->ci_feature_sefflags_edx & SEFF0EDX_IBRS) { + ibrs = 1; + } + } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0 && + ci->ci_pnfeatset >= 0x80000008) { + if (ci->ci_feature_amdspec_ebx & CPUIDEBX_IBRS_ALWAYSON) { + ibrs = 2; + } else if ((ci->ci_feature_amdspec_ebx & CPUIDEBX_IBRS) && + (ci->ci_feature_amdspec_ebx & CPUIDEBX_IBRS_PREF)) { + ibrs = 1; + } } + /* Enhanced IBRS: turn it on once on each CPU and don't touch again */ + if (ibrs == 2) + wrmsr(MSR_SPEC_CTRL, SPEC_CTRL_IBRS); + + if (replacedone) + return; + replacedone = 1; + s = splhigh(); + if (ibrs == 2 || (ci->ci_feature_sefflags_edx & SEFF0EDX_IBT)) { + extern const char _jmprax, _jmpr11, _jmpr13; + extern const short _jmprax_len, _jmpr11_len, _jmpr13_len; + codepatch_replace(CPTAG_RETPOLINE_RAX, &_jmprax, _jmprax_len); + codepatch_replace(CPTAG_RETPOLINE_R11, &_jmpr11, _jmpr11_len); + codepatch_replace(CPTAG_RETPOLINE_R13, &_jmpr13, _jmpr13_len); + } + if (!cpu_meltdown) codepatch_nop(CPTAG_MELTDOWN_NOP); else { diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index 9024948b899..27938da9f28 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.139 2023/07/28 06:18:35 guenther Exp $ */ +/* $OpenBSD: locore.S,v 1.140 2023/07/31 04:01:07 guenther Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -474,7 +474,16 @@ bogus_proc_pmap: END(cpu_switchto) NENTRY(retpoline_rax) + CODEPATCH_START JMP_RETPOLINE(rax) + CODEPATCH_END(CPTAG_RETPOLINE_RAX) +END(retpoline_rax) + +NENTRY(__x86_indirect_thunk_r11) + CODEPATCH_START + JMP_RETPOLINE(r11) + CODEPATCH_END(CPTAG_RETPOLINE_R11) +END(__x86_indirect_thunk_r11) ENTRY(cpu_idle_cycle_hlt) RETGUARD_SETUP(cpu_idle_cycle_hlt, r11) diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S index d3b31c76198..af268a5295e 100644 --- a/sys/arch/amd64/amd64/vector.S +++ b/sys/arch/amd64/amd64/vector.S @@ -1,4 +1,4 @@ -/* $OpenBSD: vector.S,v 1.93 2023/07/27 00:30:07 guenther Exp $ */ +/* $OpenBSD: vector.S,v 1.94 2023/07/31 04:01:07 guenther Exp $ */ /* $NetBSD: vector.S,v 1.5 2004/06/28 09:13:11 fvdl Exp $ */ /* @@ -1269,7 +1269,9 @@ END(ioapic_level_stubs) * Soft interrupt handlers */ NENTRY(retpoline_r13) + CODEPATCH_START JMP_RETPOLINE(r13) + CODEPATCH_END(CPTAG_RETPOLINE_R13) END(retpoline_r13) KIDTVEC(softtty) @@ -1280,7 +1282,9 @@ KIDTVEC(softtty) movl $X86_SOFTINTR_SOFTTTY,%edi call softintr_dispatch decl CPUVAR(IDEPTH) + CODEPATCH_START jmp retpoline_r13 + CODEPATCH_END(CPTAG_RETPOLINE_R13) END(Xsofttty) KIDTVEC(softnet) @@ -1291,7 +1295,9 @@ KIDTVEC(softnet) movl $X86_SOFTINTR_SOFTNET,%edi call softintr_dispatch decl CPUVAR(IDEPTH) + CODEPATCH_START jmp retpoline_r13 + CODEPATCH_END(CPTAG_RETPOLINE_R13) END(Xsoftnet) KIDTVEC(softclock) @@ -1302,5 +1308,7 @@ KIDTVEC(softclock) movl $X86_SOFTINTR_SOFTCLOCK,%edi call softintr_dispatch decl CPUVAR(IDEPTH) + CODEPATCH_START jmp retpoline_r13 + CODEPATCH_END(CPTAG_RETPOLINE_R13) END(Xsoftclock) diff --git a/sys/arch/amd64/conf/Makefile.amd64 b/sys/arch/amd64/conf/Makefile.amd64 index 7759b875d7f..6f760b174bb 100644 --- a/sys/arch/amd64/conf/Makefile.amd64 +++ b/sys/arch/amd64/conf/Makefile.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.amd64,v 1.132 2023/04/21 13:24:20 bluhm Exp $ +# $OpenBSD: Makefile.amd64,v 1.133 2023/07/31 04:01:07 guenther Exp $ # For instructions on building kernels consult the config(8) and options(4) # manual pages. @@ -72,7 +72,7 @@ COPTIMIZE= -Oz CMACHFLAGS+= -mno-retpoline -fcf-protection=none .endif .else -CMACHFLAGS+= -fcf-protection=branch +CMACHFLAGS+= -mretpoline-external-thunk -fcf-protection=branch .endif .if ${COMPILER_VERSION:Mclang} NO_INTEGR_AS= -no-integrated-as diff --git a/sys/arch/amd64/include/codepatch.h b/sys/arch/amd64/include/codepatch.h index 6401dab9f2f..6f2bdbe184e 100644 --- a/sys/arch/amd64/include/codepatch.h +++ b/sys/arch/amd64/include/codepatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: codepatch.h,v 1.17 2023/07/31 01:33:57 guenther Exp $ */ +/* $OpenBSD: codepatch.h,v 1.18 2023/07/31 04:01:07 guenther Exp $ */ /* * Copyright (c) 2014-2015 Stefan Fritsch * @@ -66,6 +66,9 @@ void codepatch_disable(void); #define CPTAG_FENCE_SWAPGS_MIS_TAKEN 11 #define CPTAG_FENCE_NO_SAFE_SMAP 12 #define CPTAG_XRSTORS 13 +#define CPTAG_RETPOLINE_RAX 14 +#define CPTAG_RETPOLINE_R11 15 +#define CPTAG_RETPOLINE_R13 16 /* * stac/clac SMAP instructions have lfence like semantics. Let's -- 2.20.1