x86/boot/compressed/64: Add CPUID sanity check to 32-bit boot-path
authorJoerg Roedel <jroedel@suse.de>
Fri, 12 Mar 2021 12:38:22 +0000 (13:38 +0100)
committerBorislav Petkov <bp@suse.de>
Thu, 18 Mar 2021 22:04:12 +0000 (23:04 +0100)
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 <jroedel@suse.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210312123824.306-7-joro@8bytes.org
arch/x86/boot/compressed/mem_encrypt.S

index ebc4a29..c1e81a8 100644 (file)
@@ -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)