x86/traps: Fix load_unaligned_zeropad() handling for shared TDX memory
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Mon, 24 Jul 2023 23:03:29 +0000 (02:03 +0300)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Jul 2023 22:29:01 +0000 (15:29 -0700)
Commit c4e34dd99f2e ("x86: simplify load_unaligned_zeropad()
implementation") changes how exceptions around load_unaligned_zeropad()
handled.  The kernel now uses the fault_address in fixup_exception() to
verify the address calculations for the load_unaligned_zeropad().

It works fine for #PF, but breaks on #VE since no fault address is
passed down to fixup_exception().

Propagating ve_info.gla down to fixup_exception() resolves the issue.

See commit 1e7769653b06 ("x86/tdx: Handle load_unaligned_zeropad()
page-cross to a shared page") for more context.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reported-by: Michael Kelley <mikelley@microsoft.com>
Fixes: c4e34dd99f2e ("x86: simplify load_unaligned_zeropad() implementation")
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/kernel/traps.c

index 58b1f20..4a817d2 100644 (file)
@@ -697,9 +697,10 @@ static bool try_fixup_enqcmd_gp(void)
 }
 
 static bool gp_try_fixup_and_notify(struct pt_regs *regs, int trapnr,
-                                   unsigned long error_code, const char *str)
+                                   unsigned long error_code, const char *str,
+                                   unsigned long address)
 {
-       if (fixup_exception(regs, trapnr, error_code, 0))
+       if (fixup_exception(regs, trapnr, error_code, address))
                return true;
 
        current->thread.error_code = error_code;
@@ -759,7 +760,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
                goto exit;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc, 0))
                goto exit;
 
        if (error_code)
@@ -1357,17 +1358,20 @@ DEFINE_IDTENTRY(exc_device_not_available)
 
 #define VE_FAULT_STR "VE fault"
 
-static void ve_raise_fault(struct pt_regs *regs, long error_code)
+static void ve_raise_fault(struct pt_regs *regs, long error_code,
+                          unsigned long address)
 {
        if (user_mode(regs)) {
                gp_user_force_sig_segv(regs, X86_TRAP_VE, error_code, VE_FAULT_STR);
                return;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code, VE_FAULT_STR))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code,
+                                   VE_FAULT_STR, address)) {
                return;
+       }
 
-       die_addr(VE_FAULT_STR, regs, error_code, 0);
+       die_addr(VE_FAULT_STR, regs, error_code, address);
 }
 
 /*
@@ -1431,7 +1435,7 @@ DEFINE_IDTENTRY(exc_virtualization_exception)
         * it successfully, treat it as #GP(0) and handle it.
         */
        if (!tdx_handle_virt_exception(regs, &ve))
-               ve_raise_fault(regs, 0);
+               ve_raise_fault(regs, 0, ve.gla);
 
        cond_local_irq_disable(regs);
 }