[linux] 02/02: [x86] KVM: fix emulation of "MOV SS, null selector" (CVE-2017-2583)

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Thu Jan 19 12:41:12 UTC 2017


This is an automated email from the git hooks/post-receive script.

carnil pushed a commit to branch sid
in repository linux.

commit f18792b8fa76201ab11f48835991c7aeada5386f
Author: Salvatore Bonaccorso <carnil at debian.org>
Date:   Thu Jan 19 13:11:54 2017 +0100

    [x86] KVM: fix emulation of "MOV SS, null selector" (CVE-2017-2583)
---
 debian/changelog                                   |   1 +
 ...x86-fix-emulation-of-MOV-SS-null-selector.patch | 107 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 3 files changed, 109 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 4245875..1ee89b2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -245,6 +245,7 @@ linux (4.9.4-1) UNRELEASED; urgency=medium
     (CVE-2016-9191)
   * tmpfs: clear S_ISGID when setting posix ACLs
   * [x86] KVM: Introduce segmented_write_std (CVE-2017-2584)
+  * [x86] KVM: fix emulation of "MOV SS, null selector" (CVE-2017-2583)
 
  -- Salvatore Bonaccorso <carnil at debian.org>  Mon, 16 Jan 2017 09:26:13 +0100
 
diff --git a/debian/patches/bugfix/x86/KVM-x86-fix-emulation-of-MOV-SS-null-selector.patch b/debian/patches/bugfix/x86/KVM-x86-fix-emulation-of-MOV-SS-null-selector.patch
new file mode 100644
index 0000000..f6d2e5d
--- /dev/null
+++ b/debian/patches/bugfix/x86/KVM-x86-fix-emulation-of-MOV-SS-null-selector.patch
@@ -0,0 +1,107 @@
+From: Paolo Bonzini <pbonzini at redhat.com>
+Date: Thu, 12 Jan 2017 15:02:32 +0100
+Subject: KVM: x86: fix emulation of "MOV SS, null selector"
+Origin: https://git.kernel.org/linus/33ab91103b3415e12457e3104f0e4517ce12d0f3
+
+This is CVE-2017-2583.  On Intel this causes a failed vmentry because
+SS's type is neither 3 nor 7 (even though the manual says this check is
+only done for usable SS, and the dmesg splat says that SS is unusable!).
+On AMD it's worse: svm.c is confused and sets CPL to 0 in the vmcb.
+
+The fix fabricates a data segment descriptor when SS is set to a null
+selector, so that CPL and SS.DPL are set correctly in the VMCS/vmcb.
+Furthermore, only allow setting SS to a NULL selector if SS.RPL < 3;
+this in turn ensures CPL < 3 because RPL must be equal to CPL.
+
+Thanks to Andy Lutomirski and Willy Tarreau for help in analyzing
+the bug and deciphering the manuals.
+
+Reported-by: Xiaohan Zhang <zhangxiaohan1 at huawei.com>
+Fixes: 79d5b4c3cd809c770d4bf9812635647016c56011
+Cc: stable at nongnu.org
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+---
+ arch/x86/kvm/emulate.c | 48 ++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 38 insertions(+), 10 deletions(-)
+
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index f36d0fa..cedbba0 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1585,7 +1585,6 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ 				    &ctxt->exception);
+ }
+ 
+-/* Does not support long mode */
+ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ 				     u16 selector, int seg, u8 cpl,
+ 				     enum x86_transfer_type transfer,
+@@ -1622,20 +1621,34 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ 
+ 	rpl = selector & 3;
+ 
+-	/* NULL selector is not valid for TR, CS and SS (except for long mode) */
+-	if ((seg == VCPU_SREG_CS
+-	     || (seg == VCPU_SREG_SS
+-		 && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
+-	     || seg == VCPU_SREG_TR)
+-	    && null_selector)
+-		goto exception;
+-
+ 	/* TR should be in GDT only */
+ 	if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
+ 		goto exception;
+ 
+-	if (null_selector) /* for NULL selector skip all following checks */
++	/* NULL selector is not valid for TR, CS and (except for long mode) SS */
++	if (null_selector) {
++		if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
++			goto exception;
++
++		if (seg == VCPU_SREG_SS) {
++			if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
++				goto exception;
++
++			/*
++			 * ctxt->ops->set_segment expects the CPL to be in
++			 * SS.DPL, so fake an expand-up 32-bit data segment.
++			 */
++			seg_desc.type = 3;
++			seg_desc.p = 1;
++			seg_desc.s = 1;
++			seg_desc.dpl = cpl;
++			seg_desc.d = 1;
++			seg_desc.g = 1;
++		}
++
++		/* Skip all following checks */
+ 		goto load;
++	}
+ 
+ 	ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
+ 	if (ret != X86EMUL_CONTINUE)
+@@ -1751,6 +1764,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
+ 				   u16 selector, int seg)
+ {
+ 	u8 cpl = ctxt->ops->cpl(ctxt);
++
++	/*
++	 * None of MOV, POP and LSS can load a NULL selector in CPL=3, but
++	 * they can load it at CPL<3 (Intel's manual says only LSS can,
++	 * but it's wrong).
++	 *
++	 * However, the Intel manual says that putting IST=1/DPL=3 in
++	 * an interrupt gate will result in SS=3 (the AMD manual instead
++	 * says it doesn't), so allow SS=3 in __load_segment_descriptor
++	 * and only forbid it here.
++	 */
++	if (seg == VCPU_SREG_SS && selector == 3 &&
++	    ctxt->mode == X86EMUL_MODE_PROT64)
++		return emulate_exception(ctxt, GP_VECTOR, 0, true);
++
+ 	return __load_segment_descriptor(ctxt, selector, seg, cpl,
+ 					 X86_TRANSFER_NONE, NULL);
+ }
+-- 
+2.1.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 140cf35..e5f9a9c 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -98,6 +98,7 @@ debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
 bugfix/all/sysctl-Drop-reference-added-by-grab_header-in-proc_s.patch
 bugfix/all/tmpfs-clear-S_ISGID-when-setting-posix-ACLs.patch
 bugfix/x86/KVM-x86-Introduce-segmented_write_std.patch
+bugfix/x86/KVM-x86-fix-emulation-of-MOV-SS-null-selector.patch
 
 # Fix exported symbol versions
 bugfix/ia64/revert-ia64-move-exports-to-definitions.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