
[ Upstream commit eab696d8e8b9c9d600be6fad8dd8dfdfaca6ca7c ] A malicious hypervisor could disable the CPUID intercept for an SEV or SEV-ES guest and trick it into the no-SEV boot path, where it could potentially reveal secrets. This is not an issue for SEV-SNP guests, as the CPUID intercept can't be disabled for those. Remove the Hypervisor CPUID bit check from the SEV detection code to protect against this kind of attack and add a Hypervisor bit equals zero check to the SME detection path to prevent non-encrypted guests from trying to enable SME. This handles the following cases: 1) SEV(-ES) guest where CPUID intercept is disabled. The guest will still see leaf 0x8000001f and the SEV bit. It can retrieve the C-bit and boot normally. 2) Non-encrypted guests with intercepted CPUID will check the SEV_STATUS MSR and find it 0 and will try to enable SME. This will fail when the guest finds MSR_K8_SYSCFG to be zero, as it is emulated by KVM. But we can't rely on that, as there might be other hypervisors which return this MSR with bit 23 set. The Hypervisor bit check will prevent that the guest tries to enable SME in this case. 3) Non-encrypted guests on SEV capable hosts with CPUID intercept disabled (by a malicious hypervisor) will try to boot into the SME path. This will fail, but it is also not considered a problem because non-encrypted guests have no protection against the hypervisor anyway. [ bp: s/non-SEV/non-encrypted/g ] Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://lkml.kernel.org/r/20210312123824.306-3-joro@8bytes.org Signed-off-by: Sasha Levin <sashal@kernel.org>
113 lines
2.2 KiB
ArmAsm
113 lines
2.2 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* AMD Memory Encryption Support
|
|
*
|
|
* Copyright (C) 2017 Advanced Micro Devices, Inc.
|
|
*
|
|
* Author: Tom Lendacky <thomas.lendacky@amd.com>
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/processor-flags.h>
|
|
#include <asm/msr.h>
|
|
#include <asm/asm-offsets.h>
|
|
|
|
.text
|
|
.code32
|
|
SYM_FUNC_START(get_sev_encryption_bit)
|
|
xor %eax, %eax
|
|
|
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
|
push %ebx
|
|
push %ecx
|
|
push %edx
|
|
|
|
movl $0x80000000, %eax /* CPUID to check the highest leaf */
|
|
cpuid
|
|
cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
|
|
jb .Lno_sev
|
|
|
|
/*
|
|
* Check for the SEV feature:
|
|
* CPUID Fn8000_001F[EAX] - Bit 1
|
|
* CPUID Fn8000_001F[EBX] - Bits 5:0
|
|
* Pagetable bit position used to indicate encryption
|
|
*/
|
|
movl $0x8000001f, %eax
|
|
cpuid
|
|
bt $1, %eax /* Check if SEV is available */
|
|
jnc .Lno_sev
|
|
|
|
movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
|
|
rdmsr
|
|
bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */
|
|
jnc .Lno_sev
|
|
|
|
movl %ebx, %eax
|
|
andl $0x3f, %eax /* Return the encryption bit location */
|
|
jmp .Lsev_exit
|
|
|
|
.Lno_sev:
|
|
xor %eax, %eax
|
|
|
|
.Lsev_exit:
|
|
pop %edx
|
|
pop %ecx
|
|
pop %ebx
|
|
|
|
#endif /* CONFIG_AMD_MEM_ENCRYPT */
|
|
|
|
ret
|
|
SYM_FUNC_END(get_sev_encryption_bit)
|
|
|
|
.code64
|
|
|
|
#include "../../kernel/sev_verify_cbit.S"
|
|
|
|
SYM_FUNC_START(set_sev_encryption_mask)
|
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
|
push %rbp
|
|
push %rdx
|
|
|
|
movq %rsp, %rbp /* Save current stack pointer */
|
|
|
|
call get_sev_encryption_bit /* Get the encryption bit position */
|
|
testl %eax, %eax
|
|
jz .Lno_sev_mask
|
|
|
|
bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
|
|
|
|
/*
|
|
* Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
|
|
* get_sev_encryption_bit() because this function is 32-bit code and
|
|
* shared between 64-bit and 32-bit boot path.
|
|
*/
|
|
movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
|
|
rdmsr
|
|
|
|
/* Store MSR value in sev_status */
|
|
shlq $32, %rdx
|
|
orq %rdx, %rax
|
|
movq %rax, sev_status(%rip)
|
|
|
|
.Lno_sev_mask:
|
|
movq %rbp, %rsp /* Restore original stack pointer */
|
|
|
|
pop %rdx
|
|
pop %rbp
|
|
#endif
|
|
|
|
xor %rax, %rax
|
|
ret
|
|
SYM_FUNC_END(set_sev_encryption_mask)
|
|
|
|
.data
|
|
|
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
|
.balign 8
|
|
SYM_DATA(sme_me_mask, .quad 0)
|
|
SYM_DATA(sev_status, .quad 0)
|
|
SYM_DATA(sev_check_data, .quad 0)
|
|
#endif
|