From ac598b0856eab65a61325fdb1eaeb8d72a71de85 Mon Sep 17 00:00:00 2001 From: Shuo A Liu Date: Wed, 8 Jul 2020 19:39:07 +0800 Subject: [PATCH] hv: Hide CET feature from guest VM Return-oriented programming (ROP), and similarly CALL/JMP-oriented programming (COP/JOP), have been the prevalent attack methodologies for stealth exploit writers targeting vulnerabilities in programs. CET (Control-flow Enforcement Technology) provides the following capabilities to defend against ROP/COP/JOP style control-flow subversion attacks: * Shadow stack: Return address protection to defend against ROP. * Indirect branch tracking: Free branch protection to defend against COP/JOP The full support of CET for Linux kernel has not been merged yet. As the first stage, hide CET from guest VM. Tracked-On: #5074 Signed-off-by: Shuo A Liu Reviewed-by: Jason Chen CJ --- hypervisor/arch/x86/guest/vcpuid.c | 24 +++++++++++++++++++++--- hypervisor/arch/x86/guest/virtual_cr.c | 7 ++++--- hypervisor/arch/x86/guest/vmsr.c | 15 ++++++++++++++- hypervisor/include/arch/x86/cpu.h | 1 + hypervisor/include/arch/x86/cpuid.h | 8 ++++++++ hypervisor/include/arch/x86/msr.h | 7 +++++++ 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpuid.c b/hypervisor/arch/x86/guest/vcpuid.c index decacc8f9..d6bfa79ec 100644 --- a/hypervisor/arch/x86/guest/vcpuid.c +++ b/hypervisor/arch/x86/guest/vcpuid.c @@ -128,6 +128,10 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t subleaf, /* mask Intel Processor Trace, since 14h is disabled */ entry->ebx &= ~CPUID_EBX_PROC_TRC; + + /* mask CET shadow stack and indirect branch tracking */ + entry->ecx &= ~CPUID_ECX_CET_SS; + entry->edx &= ~CPUID_EDX_CET_IBT; } else { entry->eax = 0U; entry->ebx = 0U; @@ -494,12 +498,26 @@ static void guest_cpuid_0dh(__unused struct acrn_vcpu *vcpu, uint32_t *eax, uint *edx = 0U; } else { cpuid_subleaf(0x0dU, subleaf, eax, ebx, ecx, edx); - if (subleaf == 0U) { + switch (subleaf) { + case 0U: /* SDM Vol.1 17-2, On processors that do not support Intel MPX, * CPUID.(EAX=0DH,ECX=0):EAX[3] and * CPUID.(EAX=0DH,ECX=0):EAX[4] will both be 0 */ - *eax &= ~ CPUID_EAX_XCR0_BNDREGS; - *eax &= ~ CPUID_EAX_XCR0_BNDCSR; + *eax &= ~(CPUID_EAX_XCR0_BNDREGS | CPUID_EAX_XCR0_BNDCSR); + break; + case 1U: + *ecx &= ~(CPUID_ECX_CET_U_STATE | CPUID_ECX_CET_S_STATE); + break; + case 11U: + case 12U: + *eax = 0U; + *ebx = 0U; + *ecx = 0U; + *edx = 0U; + break; + default: + /* No emulation for other leaves */ + break; } } } diff --git a/hypervisor/arch/x86/guest/virtual_cr.c b/hypervisor/arch/x86/guest/virtual_cr.c index 2fbf9bcfc..9c4a5fd5b 100644 --- a/hypervisor/arch/x86/guest/virtual_cr.c +++ b/hypervisor/arch/x86/guest/virtual_cr.c @@ -27,13 +27,13 @@ CR0_NE | CR0_ET | CR0_TS | CR0_EM | CR0_MP | CR0_PE) /* CR4 bits hv want to trap to track status change */ -#define CR4_TRAP_MASK (CR4_PSE | CR4_PAE | CR4_VMXE | CR4_SMEP | CR4_SMAP | CR4_PKE) +#define CR4_TRAP_MASK (CR4_PSE | CR4_PAE | CR4_VMXE | CR4_SMEP | CR4_SMAP | CR4_PKE | CR4_CET) #define CR4_RESERVED_MASK ~(CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | \ CR4_PAE | CR4_MCE | CR4_PGE | CR4_PCE | \ CR4_OSFXSR | CR4_PCIDE | CR4_OSXSAVE | \ CR4_SMEP | CR4_FSGSBASE | CR4_VMXE | \ CR4_OSXMMEXCPT | CR4_SMAP | CR4_PKE | \ - CR4_SMXE | CR4_UMIP) + CR4_SMXE | CR4_UMIP | CR4_CET) /* PAE PDPTE bits 1 ~ 2, 5 ~ 8 are always reserved */ #define PAE_PDPTE_FIXED_RESVD_BITS 0x00000000000001E6UL @@ -256,7 +256,7 @@ static bool is_cr4_write_valid(struct acrn_vcpu *vcpu, uint64_t cr4) ret = false; } else { /* Do NOT support nested guest, nor SMX */ - if (((cr4 & CR4_VMXE) != 0UL) || ((cr4 & CR4_SMXE) != 0UL)) { + if (((cr4 & CR4_VMXE) != 0UL) || ((cr4 & CR4_SMXE) != 0UL) || ((cr4 & CR4_CET) != 0UL)) { ret = false; } else { if (is_long_mode(vcpu)) { @@ -304,6 +304,7 @@ static bool is_cr4_write_valid(struct acrn_vcpu *vcpu, uint64_t cr4) * - SMEP (20) Flexible to guest * - SMAP (21) Flexible to guest * - PKE (22) Flexible to guest + * - CET (23) Trapped to hide from guest */ static void vmx_write_cr4(struct acrn_vcpu *vcpu, uint64_t cr4) { diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index 438846ae7..bb79b0fe7 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -80,7 +80,7 @@ static const uint32_t mtrr_msrs[NUM_MTRR_MSRS] = { }; /* Following MSRs are intercepted, but it throws GPs for any guest accesses */ -#define NUM_UNSUPPORTED_MSRS 104U +#define NUM_UNSUPPORTED_MSRS 111U static const uint32_t unsupported_msrs[NUM_UNSUPPORTED_MSRS] = { /* Variable MTRRs are not supported */ MSR_IA32_MTRR_PHYSBASE_0, @@ -221,6 +221,19 @@ static const uint32_t unsupported_msrs[NUM_UNSUPPORTED_MSRS] = { MSR_PRMRR_VALID_CONFIG, MSR_UNCORE_PRMRR_PHYS_BASE, MSR_UNCORE_PRMRR_PHYS_MASK, + + /* + * CET disabled: + * CPUID.07H.ECX[7] (CPUID_ECX_CET_SS) + * CPUID.07H.EDX[20] (CPUID_ECX_CET_IBT) + */ + MSR_IA32_U_CET, + MSR_IA32_S_CET, + MSR_IA32_PL0_SSP, + MSR_IA32_PL1_SSP, + MSR_IA32_PL2_SSP, + MSR_IA32_PL3_SSP, + MSR_IA32_INTERRUPT_SSP_TABLE_ADDR, }; /* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */ diff --git a/hypervisor/include/arch/x86/cpu.h b/hypervisor/include/arch/x86/cpu.h index db82e8302..fbe7eed35 100644 --- a/hypervisor/include/arch/x86/cpu.h +++ b/hypervisor/include/arch/x86/cpu.h @@ -84,6 +84,7 @@ #define CR4_SMEP (1UL<<20U) #define CR4_SMAP (1UL<<21U) #define CR4_PKE (1UL<<22U) /* Protect-key-enable */ +#define CR4_CET (1UL<<23U) /* Control-flow Enforcement Technology enable */ /* XCR0_SSE */ #define XCR0_SSE (1UL<<1U) diff --git a/hypervisor/include/arch/x86/cpuid.h b/hypervisor/include/arch/x86/cpuid.h index a39f302fa..eae8a6186 100644 --- a/hypervisor/include/arch/x86/cpuid.h +++ b/hypervisor/include/arch/x86/cpuid.h @@ -78,8 +78,12 @@ #define CPUID_EBX_SGX (1U<<2U) /* CPUID.07H:EBX.MPX */ #define CPUID_EBX_MPX (1U<<14U) +/* CPUID.07H:ECX.CET_SS */ +#define CPUID_ECX_CET_SS (1U<<7U) /* CPUID.07H:ECX.SGX_LC*/ #define CPUID_ECX_SGX_LC (1U<<30U) +/* CPUID.07H:EDX.CET_IBT */ +#define CPUID_EDX_CET_IBT (1U<<20U) /* CPUID.07H:EDX.IBRS_IBPB*/ #define CPUID_EDX_IBRS_IBPB (1U<<26U) /* CPUID.07H:EDX.STIBP*/ @@ -100,6 +104,10 @@ #define CPUID_EAX_XCR0_BNDREGS (1U<<3U) /* CPUID.0DH.EAX.XCR0_BNDCSR */ #define CPUID_EAX_XCR0_BNDCSR (1U<<4U) +/* CPUID.0DH.ECX.CET_U_STATE */ +#define CPUID_ECX_CET_U_STATE (1U<<11U) +/* CPUID.0DH.ECX.CET_S_STATE */ +#define CPUID_ECX_CET_S_STATE (1U<<12U) /* CPUID.12H.EAX.SGX1 */ #define CPUID_EAX_SGX1 (1U<<0U) /* CPUID.12H.EAX.SGX2 */ diff --git a/hypervisor/include/arch/x86/msr.h b/hypervisor/include/arch/x86/msr.h index afa57268d..f40e27b02 100644 --- a/hypervisor/include/arch/x86/msr.h +++ b/hypervisor/include/arch/x86/msr.h @@ -278,6 +278,13 @@ #define MSR_IA32_RTIT_ADDR3_A 0x00000586U #define MSR_IA32_RTIT_ADDR3_B 0x00000587U #define MSR_IA32_DS_AREA 0x00000600U +#define MSR_IA32_U_CET 0x000006A0U +#define MSR_IA32_S_CET 0x000006A2U +#define MSR_IA32_PL0_SSP 0x000006A4U +#define MSR_IA32_PL1_SSP 0x000006A5U +#define MSR_IA32_PL2_SSP 0x000006A6U +#define MSR_IA32_PL3_SSP 0x000006A7U +#define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR 0x000006A8U #define MSR_IA32_TSC_DEADLINE 0x000006E0U #define MSR_IA32_PM_ENABLE 0x00000770U #define MSR_IA32_HWP_CAPABILITIES 0x00000771U