x86/boot/compressed/64: Switch to __KERNEL_CS after GDT is loaded
authorJoerg Roedel <jroedel@suse.de>
Tue, 28 Apr 2020 15:16:22 +0000 (17:16 +0200)
committerBorislav Petkov <bp@suse.de>
Mon, 4 May 2020 17:53:08 +0000 (19:53 +0200)
When the pre-decompression code loads its first GDT in startup_64(), it
is still running on the CS value of the previous GDT. In the case of
SEV-ES, this is the EFI GDT but it can be anything depending on what has
loaded the kernel (boot loader, container runtime, etc.)

To make exception handling work (especially IRET) the CPU needs to
switch to a CS value in the current GDT, so jump to __KERNEL_CS after
the first GDT is loaded. This is prudent also as a general sanitization
of CS to a known good value.

 [ bp: Massage commit message. ]

Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200428151725.31091-13-joro@8bytes.org
arch/x86/boot/compressed/head_64.S

index 4f7e6b84be0703a62849ce1c3d1ecd9c6a29a325..6b11060c3a0f610dd56a89cdcf39793e52633051 100644 (file)
@@ -393,6 +393,14 @@ SYM_CODE_START(startup_64)
        addq    %rax, 2(%rax)
        lgdt    (%rax)
 
+       /* Reload CS so IRET returns to a CS actually in the GDT */
+       pushq   $__KERNEL_CS
+       leaq    .Lon_kernel_cs(%rip), %rax
+       pushq   %rax
+       lretq
+
+.Lon_kernel_cs:
+
        /*
         * paging_prepare() sets up the trampoline and checks if we need to
         * enable 5-level paging.