|
Joerg Roedel |
121e9e |
From: Joerg Roedel <jroedel@suse.de>
|
|
Joerg Roedel |
121e9e |
Date: Fri, 12 Mar 2021 13:38:18 +0100
|
|
Joerg Roedel |
121e9e |
Subject: x86/sev: Do not require Hypervisor CPUID bit for SEV guests
|
|
Joerg Roedel |
121e9e |
Git-commit: eab696d8e8b9c9d600be6fad8dd8dfdfaca6ca7c
|
|
Joerg Roedel |
121e9e |
Patch-mainline: v5.13-rc1
|
|
Joerg Roedel |
121e9e |
References: jsc#SLE-14337
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
A malicious hypervisor could disable the CPUID intercept for an SEV or
|
|
Joerg Roedel |
121e9e |
SEV-ES guest and trick it into the no-SEV boot path, where it could
|
|
Joerg Roedel |
121e9e |
potentially reveal secrets. This is not an issue for SEV-SNP guests,
|
|
Joerg Roedel |
121e9e |
as the CPUID intercept can't be disabled for those.
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
Remove the Hypervisor CPUID bit check from the SEV detection code to
|
|
Joerg Roedel |
121e9e |
protect against this kind of attack and add a Hypervisor bit equals zero
|
|
Joerg Roedel |
121e9e |
check to the SME detection path to prevent non-encrypted guests from
|
|
Joerg Roedel |
121e9e |
trying to enable SME.
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
This handles the following cases:
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
1) SEV(-ES) guest where CPUID intercept is disabled. The guest
|
|
Joerg Roedel |
121e9e |
will still see leaf 0x8000001f and the SEV bit. It can
|
|
Joerg Roedel |
121e9e |
retrieve the C-bit and boot normally.
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
2) Non-encrypted guests with intercepted CPUID will check
|
|
Joerg Roedel |
121e9e |
the SEV_STATUS MSR and find it 0 and will try to enable SME.
|
|
Joerg Roedel |
121e9e |
This will fail when the guest finds MSR_K8_SYSCFG to be zero,
|
|
Joerg Roedel |
121e9e |
as it is emulated by KVM. But we can't rely on that, as there
|
|
Joerg Roedel |
121e9e |
might be other hypervisors which return this MSR with bit
|
|
Joerg Roedel |
121e9e |
23 set. The Hypervisor bit check will prevent that the guest
|
|
Joerg Roedel |
121e9e |
tries to enable SME in this case.
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
3) Non-encrypted guests on SEV capable hosts with CPUID intercept
|
|
Joerg Roedel |
121e9e |
disabled (by a malicious hypervisor) will try to boot into
|
|
Joerg Roedel |
121e9e |
the SME path. This will fail, but it is also not considered
|
|
Joerg Roedel |
121e9e |
a problem because non-encrypted guests have no protection
|
|
Joerg Roedel |
121e9e |
against the hypervisor anyway.
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
[ bp: s/non-SEV/non-encrypted/g ]
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
Signed-off-by: Joerg Roedel <jroedel@suse.de>
|
|
Joerg Roedel |
121e9e |
Signed-off-by: Borislav Petkov <bp@suse.de>
|
|
Joerg Roedel |
121e9e |
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
|
|
Joerg Roedel |
121e9e |
Link: https://lkml.kernel.org/r/20210312123824.306-3-joro@8bytes.org
|
|
Joerg Roedel |
121e9e |
---
|
|
Joerg Roedel |
121e9e |
arch/x86/boot/compressed/mem_encrypt.S | 6 -----
|
|
Joerg Roedel |
121e9e |
arch/x86/kernel/sev-es-shared.c | 6 -----
|
|
Joerg Roedel |
121e9e |
arch/x86/mm/mem_encrypt_identity.c | 35 +++++++++++++++++----------------
|
|
Joerg Roedel |
121e9e |
3 files changed, 20 insertions(+), 27 deletions(-)
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
--- a/arch/x86/boot/compressed/mem_encrypt.S
|
|
Joerg Roedel |
121e9e |
+++ b/arch/x86/boot/compressed/mem_encrypt.S
|
|
Joerg Roedel |
121e9e |
@@ -23,12 +23,6 @@ ENTRY(get_sev_encryption_bit)
|
|
Joerg Roedel |
121e9e |
push %ecx
|
|
Joerg Roedel |
121e9e |
push %edx
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
- /* Check if running under a hypervisor */
|
|
Joerg Roedel |
121e9e |
- movl $1, %eax
|
|
Joerg Roedel |
121e9e |
- cpuid
|
|
Joerg Roedel |
121e9e |
- bt $31, %ecx /* Check the hypervisor bit */
|
|
Joerg Roedel |
121e9e |
- jnc .Lno_sev
|
|
Joerg Roedel |
121e9e |
-
|
|
Joerg Roedel |
121e9e |
movl $0x80000000, %eax /* CPUID to check the highest leaf */
|
|
Joerg Roedel |
121e9e |
cpuid
|
|
Joerg Roedel |
121e9e |
cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
|
|
Joerg Roedel |
121e9e |
--- a/arch/x86/kernel/sev-es-shared.c
|
|
Joerg Roedel |
121e9e |
+++ b/arch/x86/kernel/sev-es-shared.c
|
|
Joerg Roedel |
121e9e |
@@ -186,7 +186,6 @@ void __init do_vc_no_ghcb(struct pt_regs
|
|
Joerg Roedel |
121e9e |
* make it accessible to the hypervisor.
|
|
Joerg Roedel |
121e9e |
*
|
|
Joerg Roedel |
121e9e |
* In particular, check for:
|
|
Joerg Roedel |
121e9e |
- * - Hypervisor CPUID bit
|
|
Joerg Roedel |
121e9e |
* - Availability of CPUID leaf 0x8000001f
|
|
Joerg Roedel |
121e9e |
* - SEV CPUID bit.
|
|
Joerg Roedel |
121e9e |
*
|
|
Joerg Roedel |
121e9e |
@@ -194,10 +193,7 @@ void __init do_vc_no_ghcb(struct pt_regs
|
|
Joerg Roedel |
121e9e |
* can't be checked here.
|
|
Joerg Roedel |
121e9e |
*/
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
- if ((fn == 1 && !(regs->cx & BIT(31))))
|
|
Joerg Roedel |
121e9e |
- /* Hypervisor bit */
|
|
Joerg Roedel |
121e9e |
- goto fail;
|
|
Joerg Roedel |
121e9e |
- else if (fn == 0x80000000 && (regs->ax < 0x8000001f))
|
|
Joerg Roedel |
121e9e |
+ if (fn == 0x80000000 && (regs->ax < 0x8000001f))
|
|
Joerg Roedel |
121e9e |
/* SEV leaf check */
|
|
Joerg Roedel |
121e9e |
goto fail;
|
|
Joerg Roedel |
121e9e |
else if ((fn == 0x8000001f && !(regs->ax & BIT(1))))
|
|
Joerg Roedel |
121e9e |
--- a/arch/x86/mm/mem_encrypt_identity.c
|
|
Joerg Roedel |
121e9e |
+++ b/arch/x86/mm/mem_encrypt_identity.c
|
|
Joerg Roedel |
121e9e |
@@ -503,14 +503,10 @@ void __init sme_enable(struct boot_param
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
#define AMD_SME_BIT BIT(0)
|
|
Joerg Roedel |
121e9e |
#define AMD_SEV_BIT BIT(1)
|
|
Joerg Roedel |
121e9e |
- /*
|
|
Joerg Roedel |
121e9e |
- * Set the feature mask (SME or SEV) based on whether we are
|
|
Joerg Roedel |
121e9e |
- * running under a hypervisor.
|
|
Joerg Roedel |
121e9e |
- */
|
|
Joerg Roedel |
121e9e |
- eax = 1;
|
|
Joerg Roedel |
121e9e |
- ecx = 0;
|
|
Joerg Roedel |
121e9e |
- native_cpuid(&eax, &ebx, &ecx, &edx;;
|
|
Joerg Roedel |
121e9e |
- feature_mask = (ecx & BIT(31)) ? AMD_SEV_BIT : AMD_SME_BIT;
|
|
Joerg Roedel |
121e9e |
+
|
|
Joerg Roedel |
121e9e |
+ /* Check the SEV MSR whether SEV or SME is enabled */
|
|
Joerg Roedel |
121e9e |
+ sev_status = __rdmsr(MSR_AMD64_SEV);
|
|
Joerg Roedel |
121e9e |
+ feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
/*
|
|
Joerg Roedel |
121e9e |
* Check for the SME/SEV feature:
|
|
Joerg Roedel |
121e9e |
@@ -530,19 +526,26 @@ void __init sme_enable(struct boot_param
|
|
Joerg Roedel |
121e9e |
|
|
Joerg Roedel |
121e9e |
/* Check if memory encryption is enabled */
|
|
Joerg Roedel |
121e9e |
if (feature_mask == AMD_SME_BIT) {
|
|
Joerg Roedel |
121e9e |
+ /*
|
|
Joerg Roedel |
121e9e |
+ * No SME if Hypervisor bit is set. This check is here to
|
|
Joerg Roedel |
121e9e |
+ * prevent a guest from trying to enable SME. For running as a
|
|
Joerg Roedel |
121e9e |
+ * KVM guest the MSR_K8_SYSCFG will be sufficient, but there
|
|
Joerg Roedel |
121e9e |
+ * might be other hypervisors which emulate that MSR as non-zero
|
|
Joerg Roedel |
121e9e |
+ * or even pass it through to the guest.
|
|
Joerg Roedel |
121e9e |
+ * A malicious hypervisor can still trick a guest into this
|
|
Joerg Roedel |
121e9e |
+ * path, but there is no way to protect against that.
|
|
Joerg Roedel |
121e9e |
+ */
|
|
Joerg Roedel |
121e9e |
+ eax = 1;
|
|
Joerg Roedel |
121e9e |
+ ecx = 0;
|
|
Joerg Roedel |
121e9e |
+ native_cpuid(&eax, &ebx, &ecx, &edx;;
|
|
Joerg Roedel |
121e9e |
+ if (ecx & BIT(31))
|
|
Joerg Roedel |
121e9e |
+ return;
|
|
Joerg Roedel |
121e9e |
+
|
|
Joerg Roedel |
121e9e |
/* For SME, check the SYSCFG MSR */
|
|
Joerg Roedel |
121e9e |
msr = __rdmsr(MSR_K8_SYSCFG);
|
|
Joerg Roedel |
121e9e |
if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
|
|
Joerg Roedel |
121e9e |
return;
|
|
Joerg Roedel |
121e9e |
} else {
|
|
Joerg Roedel |
121e9e |
- /* For SEV, check the SEV MSR */
|
|
Joerg Roedel |
121e9e |
- msr = __rdmsr(MSR_AMD64_SEV);
|
|
Joerg Roedel |
121e9e |
- if (!(msr & MSR_AMD64_SEV_ENABLED))
|
|
Joerg Roedel |
121e9e |
- return;
|
|
Joerg Roedel |
121e9e |
-
|
|
Joerg Roedel |
121e9e |
- /* Save SEV_STATUS to avoid reading MSR again */
|
|
Joerg Roedel |
121e9e |
- sev_status = msr;
|
|
Joerg Roedel |
121e9e |
-
|
|
Joerg Roedel |
121e9e |
/* SEV state cannot be controlled by a command line option */
|
|
Joerg Roedel |
121e9e |
sme_me_mask = me_mask;
|
|
Joerg Roedel |
121e9e |
sev_enabled = true;
|