Xen Security Advisory 274 v3 (CVE-2018-14678) - Linux: Uninitialized state in x86 PV failsafe callback path
Xen.org security team <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.announce |
|---|---|
| Message-ID | <E1fpyMp-0006mM-Vn__8598.36214590377$1534349651$gmane$org@xenbits.xenproject.org> |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory CVE-2018-14678 / XSA-274
version 3
Linux: Uninitialized state in x86 PV failsafe callback path
UPDATES IN VERSION 3
====================
Fix spelling in CREDITS.
ISSUE DESCRIPTION
=================
Linux has a `failsafe` callback, invoked by Xen under certain
conditions. Normally in this failsafe callback, error_entry is paired
with error_exit; and error_entry uses %ebx to communicate to
error_exit whether to use the user or kernel return path.
Unfortunately, on 64-bit PV Xen on x86, error_exit is called without
error_entry being called first, leaving %ebx with an invalid value.
IMPACT
======
A rogue user-space program could crash a guest kernel. Privilege
escalation cannot be ruled out.
VULNERABLE SYSTEMS
==================
Only 64-bit x86 PV Linux systems are vulnerable.
All versions of Linux are vulnerable.
MITIGATION
==========
Switching to HVM or PVH guests will mitigate this issue.
CREDITS
=======
This issue was discovered by M. Vefa Bicakci, and recognized as a
security issue by Andy Lutomirski.
RESOLUTION
==========
Applying the appropriate attached patch resolves this issue.
NB this patch has not been accepted into Linux upstream yet. An
updated advisory will be sent if the fix upstreamed looks
significantly different.
xsa274-linux-4.17.patch Linux 4.17
$ sha256sum xsa274*
0c30cb13d1d573f446c8cb8d4824ffad8ef9149a7589a19ef9bcc83c07bddcf5 xsa274-linux-4.17.patch
$
NOTE ON THE LACK OF EMBARGO
===========================
The patch for this issue was published on linux-kernel without being
first reported to the XenProject Security Team.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAEBCAAGBQJbdFA5AAoJEIP+FMlX6CvZWQQIAIxMK2w6CsH2aNQRDiDrgcBc
2FkBbroS5I1XHEhWVyO19aPhp1R3mYNU+pTUUFOevQuKvTP0nuZ0csgk5LUj9UP7
EE/3vM3jkAfmIIuXCAegOcznnEl6Wi9aMKGVXcxMkRu9qjKStGr4We5qvmdPncUj
DkTdD6VbmM/Q665b0jU4j2aZPDMsH63qrsbz1rsnPAlYUi1R+yKw56Q5UdRJK17j
Jc74v+elyqOkFq7QwH1usfnko+DQziLyLqEBQOztTSps2qYM+VwHLAZkhxNyuLsu
2x9/1D8XoZ+BHvVsVe50QmoNcJViMMunnHNhWYHmtXLYFErwUOt48N1vl+3xFpo=
=k4Ak
-----END PGP SIGNATURE-----
_______________________________________________
Xen-announce mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-announce
xsa274-linux-4.17.patch
(application/octet-stream, 4 KB)
From 8df635007e0737887522eebee886155602b8809b Mon Sep 17 00:00:00 2001 From: Andy Lutomirski <[email protected]> Date: Sun, 22 Jul 2018 11:05:09 -0700 Subject: [PATCH] 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 3ac6d8c787b8 ("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.] Cc: Brian Gerst <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Dominik Brodowski <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: Juergen Gross <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Fixes: 3ac6d8c787b8 ("x86/entry/64: Clear registers for exceptions/interrupts, to reduce speculation attack surface") Reported-and-tested-by: "M. Vefa Bicakci" <[email protected]> Signed-off-by: Andy Lutomirski <[email protected]> --- arch/x86/entry/entry_64.S | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 73a522d53b53..8ae7ffda8f98 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -981,7 +981,7 @@ ENTRY(\sym) call \do_sym - jmp error_exit /* %ebx: no swapgs flag */ + jmp error_exit .endif END(\sym) .endm @@ -1222,7 +1222,6 @@ END(paranoid_exit) /* * Save all registers in pt_regs, and switch GS if needed. - * Return: EBX=0: came from user mode; EBX=1: otherwise */ ENTRY(error_entry) UNWIND_HINT_FUNC @@ -1269,7 +1268,6 @@ ENTRY(error_entry) * for these here too. */ .Lerror_kernelspace: - incl %ebx leaq native_irq_return_iret(%rip), %rcx cmpq %rcx, RIP+8(%rsp) je .Lerror_bad_iret @@ -1303,28 +1301,20 @@ ENTRY(error_entry) /* * Pretend that the exception came from user mode: set up pt_regs - * as if we faulted immediately after IRET and clear EBX so that - * error_exit knows that we will be returning to user mode. + * as if we faulted immediately after IRET. */ mov %rsp, %rdi call fixup_bad_iret mov %rax, %rsp - decl %ebx jmp .Lerror_entry_from_usermode_after_swapgs END(error_entry) - -/* - * On entry, EBX is a "return to kernel mode" flag: - * 1: already in kernel mode, don't need SWAPGS - * 0: user gsbase is loaded, we need SWAPGS and standard preparation for return to usermode - */ ENTRY(error_exit) UNWIND_HINT_REGS DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF - testl %ebx, %ebx - jnz retint_kernel + testb $3, CS(%rsp) + jz retint_kernel jmp retint_user END(error_exit) -- 2.18.0