From: Joerg Roedel <jroe...@suse.de>

The 32-bit #VC handler has no GHCB and can only handle CPUID exit codes.
It is needed by the early boot code to handle #VC exceptions raised in
verify_cpu() and to get the position of the C bit.

But the CPUID information comes from the hypervisor, which is untrusted
and might return results which trick the guest into the no-SEV boot path
with no C bit set in the page-tables. All data written to memory would
then be unencrypted and could leak sensitive data to the hypervisor.

Add sanity checks to the 32-bit boot #VC handler to make sure the
hypervisor does not pretend that SEV is not enabled.

Signed-off-by: Joerg Roedel <jroe...@suse.de>
---
 arch/x86/boot/compressed/mem_encrypt.S | 28 ++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/x86/boot/compressed/mem_encrypt.S 
b/arch/x86/boot/compressed/mem_encrypt.S
index e915f4906477..0211eddefeb0 100644
--- a/arch/x86/boot/compressed/mem_encrypt.S
+++ b/arch/x86/boot/compressed/mem_encrypt.S
@@ -139,6 +139,26 @@ SYM_CODE_START(startup32_vc_handler)
        jnz     .Lfail
        movl    %edx, 0(%esp)           # Store result
 
+       /*
+        * Sanity check CPUID results from the Hypervisor. See comment in
+        * do_vc_no_ghcb() for more details on why this is necessary.
+        */
+
+       /* Fail if SEV leaf not available in CPUID[0x80000000].EAX */
+       cmpl    $0x80000000, %ebx
+       jne     .Lcheck_sev
+       cmpl    $0x8000001f, 12(%esp)
+       jb      .Lfail
+       jmp     .Ldone
+
+.Lcheck_sev:
+       /* Fail if SEV bit not set in CPUID[0x8000001f].EAX[1] */
+       cmpl    $0x8000001f, %ebx
+       jne     .Ldone
+       btl     $1, 12(%esp)
+       jnc     .Lfail
+
+.Ldone:
        popl    %edx
        popl    %ecx
        popl    %ebx
@@ -152,6 +172,14 @@ SYM_CODE_START(startup32_vc_handler)
 
        iret
 .Lfail:
+       /* Send terminate request to Hypervisor */
+       movl    $0x100, %eax
+       xorl    %edx, %edx
+       movl    $MSR_AMD64_SEV_ES_GHCB, %ecx
+       wrmsr
+       rep; vmmcall
+
+       /* If request fails, go to hlt loop */
        hlt
        jmp .Lfail
 SYM_CODE_END(startup32_vc_handler)
-- 
2.30.1

Reply via email to