Re: [PATCH] hv: cve hotfix: Disable RRSBA on platform using retpoline


Eddie Dong
 

Acked-by: Eddie Dong <eddie.dong@...>

-----Original Message-----
From: Liu, Yifan1 <yifan1.liu@...>
Sent: Monday, July 18, 2022 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>; Mao, Junjie <junjie.mao@...>;
Li, Fei1 <fei1.li@...>; Huang, Yonghua <yonghua.huang@...>; Liu,
Yifan1 <yifan1.liu@...>
Subject: [PATCH] hv: cve hotfix: Disable RRSBA on platform using retpoline

From: Yifan Liu <yifan1.liu@...>

For platform that supports RRSBA (Restricted Return Stack Buffer Alternate),
using retpoline may not be sufficient to guard against branch history injection
or intra-mode branch target injection. RRSBA must be disabled to prevent CPUs
from using alternate predictors for RETs.

Quoting Intel CVE-2022-0001/CVE-2022-0002:

Where software is using retpoline as a mitigation for BHI or intra-mode BTI,
and the processor both enumerates RRSBA and enumerates RRSBA_DIS
controls, it should disable this behavior.
...
Software using retpoline as a mitigation for BHI or intra-mode BTI should use
these new indirect predictor controls to disable alternate predictors for RETs.

See: https://www.intel.com/content/www/us/en/developer/articles/technical/
software-security-guidance/technical-documentation/branch-history-
injection.html

Signed-off-by: Yifan Liu <yifan1.liu@...>
---
hypervisor/arch/x86/cpu.c | 4 +++
hypervisor/arch/x86/cpu_caps.c | 3 ++
hypervisor/arch/x86/security.c | 36 +++++++++++++++++++
hypervisor/include/arch/x86/asm/cpu_caps.h | 3 +-
hypervisor/include/arch/x86/asm/cpufeatures.h | 3 ++
hypervisor/include/arch/x86/asm/msr.h | 2 ++
hypervisor/include/arch/x86/asm/security.h | 1 +
7 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index
80d50baee..bbb71241e 100644
--- a/hypervisor/arch/x86/cpu.c
+++ b/hypervisor/arch/x86/cpu.c
@@ -231,6 +231,10 @@ void init_pcpu_post(uint16_t pcpu_id)

init_pcpu_xsave();

+#ifdef CONFIG_RETPOLINE
+ disable_rrsba();
+#endif
+
if (pcpu_id == BSP_CPU_ID) {
/* Print Hypervisor Banner */
print_hv_banner();
diff --git a/hypervisor/arch/x86/cpu_caps.c b/hypervisor/arch/x86/cpu_caps.c
index 74b4d1228..64f2c23d0 100644
--- a/hypervisor/arch/x86/cpu_caps.c
+++ b/hypervisor/arch/x86/cpu_caps.c
@@ -355,6 +355,9 @@ void init_pcpu_capabilities(void)
&boot_cpu_data.cpuid_leaves[FEAT_7_0_ECX],
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX]);

+ cpuid_subleaf(CPUID_EXTEND_FEATURE, 0x2U, &unused, &unused,
&unused,
+ &boot_cpu_data.cpuid_leaves[FEAT_7_2_EDX]);
+
cpuid_subleaf(CPUID_MAX_EXTENDED_FUNCTION, 0x0U,
&boot_cpu_data.extended_cpuid_level,
&unused, &unused, &unused);
diff --git a/hypervisor/arch/x86/security.c b/hypervisor/arch/x86/security.c
index af4ed6597..220f4c627 100644
--- a/hypervisor/arch/x86/security.c
+++ b/hypervisor/arch/x86/security.c
@@ -44,6 +44,42 @@ static void detect_ibrs(void) #endif }

+#ifdef CONFIG_RETPOLINE
+/* For platform that supports RRSBA (Restricted Return Stack Buffer
+Alternate),
+ * using retpoline may not be sufficient to guard against branch
+history injection (BHI)
+ * or Intra-mode branch target injection (IMBTI). RRSBA must be
+disabled to
+ * prevent CPUs from using alternate predictors for RETs.
+ *
+ * Quoting Intel CVE-2022-0001/CVE-2022-0002 documentation:
+ *
+ * Where software is using retpoline as a mitigation for BHI or
+intra-mode BTI,
+ * and the processor both enumerates RRSBA and enumerates RRSBA_DIS
+controls,
+ * it should disable this behavior.
+ * ...
+ * Software using retpoline as a mitigation for BHI or intra-mode BTI
+should use
+ * these new indirect predictor controls to disable alternate predictors for
RETs.
+ *
+ * See:
+https://www.intel.com/content/www/us/en/developer/articles/technical/
+ *
+software-security-guidance/technical-documentation/branch-history-injec
+tion.html
+ */
+void disable_rrsba(void) {
+ uint64_t v, x86_arch_caps;
+ bool rrsba_behavior = false;
+
+ if (pcpu_has_cap(X86_FEATURE_ARCH_CAP)) {
+ x86_arch_caps = msr_read(MSR_IA32_ARCH_CAPABILITIES);
+ rrsba_behavior = ((x86_arch_caps &
IA32_ARCH_CAP_RESTRICTED_RSBA) != 0UL);
+ }
+
+ if (rrsba_behavior && pcpu_has_cap(X86_FEATURE_RRSBA_CTRL)) {
+ v = msr_read(MSR_IA32_SPEC_CTRL);
+ /* Setting SPEC_RRSBA_DIS_S disables RRSBA behavior for
CPL0/1/2 */
+ v |= SPEC_RRSBA_DIS_S;
+ msr_write(MSR_IA32_SPEC_CTRL, v);
+ }
+}
+#endif
+
int32_t get_ibrs_type(void)
{
return ibrs_type;
diff --git a/hypervisor/include/arch/x86/asm/cpu_caps.h
b/hypervisor/include/arch/x86/asm/cpu_caps.h
index 6558cc61d..9ac25db67 100644
--- a/hypervisor/include/arch/x86/asm/cpu_caps.h
+++ b/hypervisor/include/arch/x86/asm/cpu_caps.h
@@ -29,7 +29,8 @@
#define FEAT_D_1_EAX 11U /* CPUID[D][1].EAX */
#define FEAT_D_1_ECX 13U /* CPUID[D][1].ECX */
#define FEAT_D_1_EDX 14U /* CPUID[D][1].EDX */
-#define FEATURE_WORDS 15U
+#define FEAT_7_2_EDX 15U /*
CPUID[EAX=7,ECX=2].EDX */
+#define FEATURE_WORDS 16U

struct cpuinfo_x86 {
/* SDM 2-2 Vol.4 Table 2-1 uses DisplayFamily_DisplayModel to diff --
git a/hypervisor/include/arch/x86/asm/cpufeatures.h
b/hypervisor/include/arch/x86/asm/cpufeatures.h
index 42dc28d23..2ecc06fb7 100644
--- a/hypervisor/include/arch/x86/asm/cpufeatures.h
+++ b/hypervisor/include/arch/x86/asm/cpufeatures.h
@@ -92,6 +92,9 @@
#define X86_FEATURE_CORE_CAP ((FEAT_7_0_EDX << 5U) + 30U)
#define X86_FEATURE_SSBD ((FEAT_7_0_EDX << 5U) + 31U)

+/* Intel-defined CPU features, CPUID level 0x00000007, sub 0x2 (EDX)*/
+#define X86_FEATURE_RRSBA_CTRL ((FEAT_7_2_EDX << 5U) + 2U)
+
/* Intel-defined CPU features, CPUID level 0x80000001 (EDX)*/
#define X86_FEATURE_NX ((FEAT_8000_0001_EDX << 5U) +
20U)
#define X86_FEATURE_PAGE1GB ((FEAT_8000_0001_EDX << 5U) + 26U)
diff --git a/hypervisor/include/arch/x86/asm/msr.h
b/hypervisor/include/arch/x86/asm/msr.h
index 2ea22b0e5..bf73c6a10 100644
--- a/hypervisor/include/arch/x86/asm/msr.h
+++ b/hypervisor/include/arch/x86/asm/msr.h
@@ -657,6 +657,7 @@ void update_msr_bitmap_x2apic_passthru(struct
acrn_vcpu *vcpu);
/* SPEC & PRED bit */
#define SPEC_ENABLE_IBRS (1U << 0U)
#define SPEC_ENABLE_STIBP (1U << 1U)
+#define SPEC_RRSBA_DIS_S (1U << 6U)
#define PRED_SET_IBPB (1U << 0U)

/* IA32 ARCH Capabilities bit */
@@ -667,6 +668,7 @@ void update_msr_bitmap_x2apic_passthru(struct
acrn_vcpu *vcpu);
#define IA32_ARCH_CAP_SSB_NO (1UL << 4U)
#define IA32_ARCH_CAP_MDS_NO (1UL << 5U)
#define IA32_ARCH_CAP_IF_PSCHANGE_MC_NO (1UL << 6U)
+#define IA32_ARCH_CAP_RESTRICTED_RSBA (1UL << 19U)

/* Flush L1 D-cache */
#define IA32_L1D_FLUSH (1UL << 0U)
diff --git a/hypervisor/include/arch/x86/asm/security.h
b/hypervisor/include/arch/x86/asm/security.h
index c210a88d7..cf357c423 100644
--- a/hypervisor/include/arch/x86/asm/security.h
+++ b/hypervisor/include/arch/x86/asm/security.h
@@ -23,6 +23,7 @@ bool check_cpu_security_cap(void); void
cpu_internal_buffers_clear(void); bool is_ept_force_4k_ipage(void); uint64_t
get_random_value(void);
+void disable_rrsba(void);

#ifdef STACK_PROTECTOR
struct stack_canary {
--
2.25.1

Join acrn-dev@lists.projectacrn.org to automatically receive all group messages.