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;