diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 461e05792..13ffb3f59 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 7651abe98..b321fa17f 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 12d8963ca..f4032b040 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-injection.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 6cb6ef2e5..8d634d981 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 3f354874e..9d493b64d 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 7a21fa33c..da82c7c3e 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 25834a0a8..6f16b0e06 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 {