Skip to content

Commit b3681dd

Browse files
amlutoIngo Molnar
authored and
Ingo Molnar
committed
x86/entry/64: Remove %ebx handling from error_entry/exit
error_entry and error_exit communicate the user vs. kernel status of the frame using %ebx. This is unnecessary -- the information is in regs->cs. Just use regs->cs. This makes error_entry simpler and makes error_exit more robust. It also fixes a nasty bug. Before all the Spectre nonsense, the xen_failsafe_callback entry point returned like this: ALLOC_PT_GPREGS_ON_STACK SAVE_C_REGS SAVE_EXTRA_REGS ENCODE_FRAME_POINTER jmp error_exit And it did not go through error_entry. This was bogus: RBX contained garbage, and error_exit expected a flag in RBX. Fortunately, it generally contained *nonzero* garbage, so the correct code path was used. As part of the Spectre fixes, code was added to clear RBX to mitigate certain speculation attacks. Now, depending on kernel configuration, RBX got zeroed and, when running some Wine workloads, the kernel crashes. This was introduced by: commit 3ac6d8c ("x86/entry/64: Clear registers for exceptions/interrupts, to reduce speculation attack surface") With this patch applied, RBX is no longer needed as a flag, and the problem goes away. I suspect that malicious userspace could use this bug to crash the kernel even without the offending patch applied, though. [ Historical note: I wrote this patch as a cleanup before I was aware of the bug it fixed. ] [ Note to stable maintainers: this should probably get applied to all kernels. If you're nervous about that, a more conservative fix to add xorl %ebx,%ebx; incl %ebx before the jump to error_exit should also fix the problem. ] Reported-and-tested-by: M. Vefa Bicakci <[email protected]> Signed-off-by: Andy Lutomirski <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: Dominik Brodowski <[email protected]> Cc: Greg KH <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Juergen Gross <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Fixes: 3ac6d8c ("x86/entry/64: Clear registers for exceptions/interrupts, to reduce speculation attack surface") Link: http://lkml.kernel.org/r/b5010a090d3586b2d6e06c7ad3ec5542d1241c45.1532282627.git.luto@kernel.org Signed-off-by: Ingo Molnar <[email protected]>
1 parent d9e6dbc commit b3681dd

File tree

1 file changed

+4
-14
lines changed

1 file changed

+4
-14
lines changed

arch/x86/entry/entry_64.S

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ ENTRY(\sym)
981981

982982
call \do_sym
983983

984-
jmp error_exit /* %ebx: no swapgs flag */
984+
jmp error_exit
985985
.endif
986986
END(\sym)
987987
.endm
@@ -1222,7 +1222,6 @@ END(paranoid_exit)
12221222

12231223
/*
12241224
* Save all registers in pt_regs, and switch GS if needed.
1225-
* Return: EBX=0: came from user mode; EBX=1: otherwise
12261225
*/
12271226
ENTRY(error_entry)
12281227
UNWIND_HINT_FUNC
@@ -1269,7 +1268,6 @@ ENTRY(error_entry)
12691268
* for these here too.
12701269
*/
12711270
.Lerror_kernelspace:
1272-
incl %ebx
12731271
leaq native_irq_return_iret(%rip), %rcx
12741272
cmpq %rcx, RIP+8(%rsp)
12751273
je .Lerror_bad_iret
@@ -1303,28 +1301,20 @@ ENTRY(error_entry)
13031301

13041302
/*
13051303
* Pretend that the exception came from user mode: set up pt_regs
1306-
* as if we faulted immediately after IRET and clear EBX so that
1307-
* error_exit knows that we will be returning to user mode.
1304+
* as if we faulted immediately after IRET.
13081305
*/
13091306
mov %rsp, %rdi
13101307
call fixup_bad_iret
13111308
mov %rax, %rsp
1312-
decl %ebx
13131309
jmp .Lerror_entry_from_usermode_after_swapgs
13141310
END(error_entry)
13151311

1316-
1317-
/*
1318-
* On entry, EBX is a "return to kernel mode" flag:
1319-
* 1: already in kernel mode, don't need SWAPGS
1320-
* 0: user gsbase is loaded, we need SWAPGS and standard preparation for return to usermode
1321-
*/
13221312
ENTRY(error_exit)
13231313
UNWIND_HINT_REGS
13241314
DISABLE_INTERRUPTS(CLBR_ANY)
13251315
TRACE_IRQS_OFF
1326-
testl %ebx, %ebx
1327-
jnz retint_kernel
1316+
testb $3, CS(%rsp)
1317+
jz retint_kernel
13281318
jmp retint_user
13291319
END(error_exit)
13301320

0 commit comments

Comments
 (0)