[linux] 15/18: [x86] KVM: drop error recovery in em_jmp_far and em_ret_far (CVE-2016-9756)
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Thu Dec 29 03:44:12 UTC 2016
This is an automated email from the git hooks/post-receive script.
benh pushed a commit to branch jessie
in repository linux.
commit de565a48b2cc33137cb4efd0743fb38c8c3bd0dc
Author: Ben Hutchings <ben at decadent.org.uk>
Date: Wed Dec 28 23:46:52 2016 +0000
[x86] KVM: drop error recovery in em_jmp_far and em_ret_far (CVE-2016-9756)
---
debian/changelog | 1 +
...p-error-recovery-in-em_jmp_far-and-em_ret.patch | 125 +++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 127 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 2d8f8e4..53006ac 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -506,6 +506,7 @@ linux (3.16.39-1) UNRELEASED; urgency=medium
* sctp: validate chunk len before actually using it (CVE-2016-9555)
* sg_write()/bsg_write() is not fit to be called under KERNEL_DS
(CVE-2016-9576)
+ * [x86] KVM: drop error recovery in em_jmp_far and em_ret_far (CVE-2016-9756)
[ Julien Cristau ]
* hwrng: Add chaoskey driver, backported from 4.8 (Closes: #839616)
diff --git a/debian/patches/bugfix/x86/kvm-x86-drop-error-recovery-in-em_jmp_far-and-em_ret.patch b/debian/patches/bugfix/x86/kvm-x86-drop-error-recovery-in-em_jmp_far-and-em_ret.patch
new file mode 100644
index 0000000..fe1a31a
--- /dev/null
+++ b/debian/patches/bugfix/x86/kvm-x86-drop-error-recovery-in-em_jmp_far-and-em_ret.patch
@@ -0,0 +1,125 @@
+From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= <rkrcmar at redhat.com>
+Date: Wed, 23 Nov 2016 21:15:00 +0100
+Subject: KVM: x86: drop error recovery in em_jmp_far and em_ret_far
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/linus/2117d5398c81554fbf803f5fd1dc55eb78216c0c
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2016-9756
+
+em_jmp_far and em_ret_far assumed that setting IP can only fail in 64
+bit mode, but syzkaller proved otherwise (and SDM agrees).
+Code segment was restored upon failure, but it was left uninitialized
+outside of long mode, which could lead to a leak of host kernel stack.
+We could have fixed that by always saving and restoring the CS, but we
+take a simpler approach and just break any guest that manages to fail
+as the error recovery is error-prone and modern CPUs don't need emulator
+for this.
+
+Found by syzkaller:
+
+ WARNING: CPU: 2 PID: 3668 at arch/x86/kvm/emulate.c:2217 em_ret_far+0x428/0x480
+ Kernel panic - not syncing: panic_on_warn set ...
+
+ CPU: 2 PID: 3668 Comm: syz-executor Not tainted 4.9.0-rc4+ #49
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+ [...]
+ Call Trace:
+ [...] __dump_stack lib/dump_stack.c:15
+ [...] dump_stack+0xb3/0x118 lib/dump_stack.c:51
+ [...] panic+0x1b7/0x3a3 kernel/panic.c:179
+ [...] __warn+0x1c4/0x1e0 kernel/panic.c:542
+ [...] warn_slowpath_null+0x2c/0x40 kernel/panic.c:585
+ [...] em_ret_far+0x428/0x480 arch/x86/kvm/emulate.c:2217
+ [...] em_ret_far_imm+0x17/0x70 arch/x86/kvm/emulate.c:2227
+ [...] x86_emulate_insn+0x87a/0x3730 arch/x86/kvm/emulate.c:5294
+ [...] x86_emulate_instruction+0x520/0x1ba0 arch/x86/kvm/x86.c:5545
+ [...] emulate_instruction arch/x86/include/asm/kvm_host.h:1116
+ [...] complete_emulated_io arch/x86/kvm/x86.c:6870
+ [...] complete_emulated_mmio+0x4e9/0x710 arch/x86/kvm/x86.c:6934
+ [...] kvm_arch_vcpu_ioctl_run+0x3b7a/0x5a90 arch/x86/kvm/x86.c:6978
+ [...] kvm_vcpu_ioctl+0x61e/0xdd0 arch/x86/kvm/../../../virt/kvm/kvm_main.c:2557
+ [...] vfs_ioctl fs/ioctl.c:43
+ [...] do_vfs_ioctl+0x18c/0x1040 fs/ioctl.c:679
+ [...] SYSC_ioctl fs/ioctl.c:694
+ [...] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685
+ [...] entry_SYSCALL_64_fastpath+0x1f/0xc2
+
+Reported-by: Dmitry Vyukov <dvyukov at google.com>
+Cc: stable at vger.kernel.org
+Fixes: d1442d85cc30 ("KVM: x86: Handle errors when RIP is set during far jumps")
+Signed-off-by: Radim Krčmář <rkrcmar at redhat.com>
+[bwh: Backported to 3.16: adjust context]
+---
+ arch/x86/kvm/emulate.c | 36 +++++++++++-------------------------
+ 1 file changed, 11 insertions(+), 25 deletions(-)
+
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1983,16 +1983,10 @@ static int em_iret(struct x86_emulate_ct
+ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
+ {
+ int rc;
+- unsigned short sel, old_sel;
+- struct desc_struct old_desc, new_desc;
+- const struct x86_emulate_ops *ops = ctxt->ops;
++ unsigned short sel;
++ struct desc_struct new_desc;
+ u8 cpl = ctxt->ops->cpl(ctxt);
+
+- /* Assignment of RIP may only fail in 64-bit mode */
+- if (ctxt->mode == X86EMUL_MODE_PROT64)
+- ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
+- VCPU_SREG_CS);
+-
+ memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
+
+ rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+@@ -2001,12 +1995,10 @@ static int em_jmp_far(struct x86_emulate
+ return rc;
+
+ rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+- if (rc != X86EMUL_CONTINUE) {
+- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+- /* assigning eip failed; restore the old cs */
+- ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
+- return rc;
+- }
++ /* Error handling is not implemented. */
++ if (rc != X86EMUL_CONTINUE)
++ return X86EMUL_UNHANDLEABLE;
++
+ return rc;
+ }
+
+@@ -2072,14 +2064,8 @@ static int em_ret_far(struct x86_emulate
+ {
+ int rc;
+ unsigned long eip, cs;
+- u16 old_cs;
+ int cpl = ctxt->ops->cpl(ctxt);
+- struct desc_struct old_desc, new_desc;
+- const struct x86_emulate_ops *ops = ctxt->ops;
+-
+- if (ctxt->mode == X86EMUL_MODE_PROT64)
+- ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
+- VCPU_SREG_CS);
++ struct desc_struct new_desc;
+
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+ if (rc != X86EMUL_CONTINUE)
+@@ -2095,10 +2081,10 @@ static int em_ret_far(struct x86_emulate
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+ rc = assign_eip_far(ctxt, eip, new_desc.l);
+- if (rc != X86EMUL_CONTINUE) {
+- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+- ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+- }
++ /* Error handling is not implemented. */
++ if (rc != X86EMUL_CONTINUE)
++ return X86EMUL_UNHANDLEABLE;
++
+ return rc;
+ }
+
diff --git a/debian/patches/series b/debian/patches/series
index c2ff3d1..4e08748 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -673,6 +673,7 @@ bugfix/all/packet-fix-race-condition-in-packet_set_ring.patch
bugfix/x86/fix-potential-infoleak-in-older-kernels.patch
bugfix/all/sctp-validate-chunk-len-before-actually-using-it.patch
bugfix/all/sg_write-bsg_write-is-not-fit-to-be-called-under-ker.patch
+bugfix/x86/kvm-x86-drop-error-recovery-in-em_jmp_far-and-em_ret.patch
# Fix ABI changes
debian/of-fix-abi-changes.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git
More information about the Kernel-svn-changes
mailing list