[xen/f19] Insufficient restrictions on certain MMU update hypercalls, Missing privilege level checks in x86 em

myoung myoung at fedoraproject.org
Wed Nov 19 20:55:18 UTC 2014


commit bf4ddc0bc7213422cf014333e211dbd5ce2ded71
Author: Michael Young <m.a.young at durham.ac.uk>
Date:   Wed Nov 19 20:54:17 2014 +0000

    Insufficient restrictions on certain MMU update hypercalls,
    Missing privilege level checks in x86 emulation of far branches,
    Add fix for CVE-2014-0150 to qemu-dm, though it probably isn't
    exploitable from xen

 CVE-2014-0150.patch      |   11 +++
 xen.spec                 |   16 +++++-
 xsa109-4.2.patch         |   25 +++++++
 xsa110-4.3-and-4.2.patch |  156 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 1 deletions(-)
---
diff --git a/CVE-2014-0150.patch b/CVE-2014-0150.patch
new file mode 100644
index 0000000..adcbcc7
--- /dev/null
+++ b/CVE-2014-0150.patch
@@ -0,0 +1,11 @@
+--- xen-4.4.1/tools/qemu-xen-traditional/hw/virtio-net.c.orig	2014-07-02 15:54:37.000000000 +0100
++++ xen-4.4.1/tools/qemu-xen-traditional/hw/virtio-net.c	2014-11-18 20:50:13.593122915 +0000
+@@ -192,7 +192,7 @@
+         return VIRTIO_NET_ERR;
+ 
+     if (mac_data.entries) {
+-        if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
++        if (n->mac_table.in_use <= MAC_TABLE_ENTRIES - mac_data.entries) {
+             memcpy(n->mac_table.macs + (n->mac_table.in_use * ETH_ALEN),
+                    elem->out_sg[2].iov_base + sizeof(mac_data),
+                    mac_data.entries * ETH_ALEN);
diff --git a/xen.spec b/xen.spec
index 841841a..9ed202f 100644
--- a/xen.spec
+++ b/xen.spec
@@ -27,7 +27,7 @@
 Summary: Xen is a virtual machine monitor
 Name:    xen
 Version: 4.2.5
-Release: 3%{?dist}
+Release: 4%{?dist}
 Group:   Development/Libraries
 License: GPLv2+ and LGPLv2+ and BSD
 URL:     http://xen.org/
@@ -84,6 +84,9 @@ Patch107: xsa104.patch
 Patch108: xsa105.patch
 Patch109: xsa106.patch
 Patch110: xsa108.patch
+Patch111: xsa109-4.2.patch
+Patch112: xsa110-4.3-and-4.2.patch
+Patch113: CVE-2014-0150.patch
 
 Patch100: xen-configure-xend.patch
 
@@ -258,6 +261,9 @@ manage Xen virtual machines.
 %patch108 -p1
 %patch109 -p1
 %patch110 -p1
+%patch111 -p1
+%patch112 -p1
+%patch113 -p1
 
 %patch100 -p1
 
@@ -751,6 +757,14 @@ rm -rf %{buildroot}
 %endif
 
 %changelog
+* Wed Nov 19 2014 Michael Young <m.a.young at durham.ac.uk> - 4.2.5-4
+- Insufficient restrictions on certain MMU update hypercalls [XSA-109,
+	CVE-2014-8594] (#1165205)
+- Missing privilege level checks in x86 emulation of far branches [XSA-110,
+	CVE-2014-8595] (#1165204)
+- Add fix for CVE-2014-0150 to qemu-dm, though it probably isn't
+	exploitable from xen (#1086776)
+
 * Wed Oct 01 2014 Michael Young <m.a.young at durham.ac.uk> - 4.2.5-3
 - Improper MSR range used for x2APIC emulation [XSA-108, CVE-2014-7188]
 	(#1148465)
diff --git a/xsa109-4.2.patch b/xsa109-4.2.patch
new file mode 100644
index 0000000..8defc6a
--- /dev/null
+++ b/xsa109-4.2.patch
@@ -0,0 +1,25 @@
+x86: don't allow page table updates on non-PV page tables in do_mmu_update()
+
+paging_write_guest_entry() and paging_cmpxchg_guest_entry() aren't
+consistently supported for non-PV guests (they'd deref NULL for PVH or
+non-HAP HVM ones). Don't allow respective MMU_* operations on the
+page tables of such domains.
+
+This is XSA-109.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+Acked-by: Tim Deegan <tim at xen.org>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -3800,6 +3800,10 @@ long do_mmu_update(
+         {
+             p2m_type_t p2mt;
+ 
++            rc = -EOPNOTSUPP;
++            if ( unlikely(paging_mode_refcounts(pt_owner)) )
++                break;
++
+             rc = xsm_mmu_normal_update(d, pt_owner, pg_owner, req.val);
+             if ( rc )
+                 break;
diff --git a/xsa110-4.3-and-4.2.patch b/xsa110-4.3-and-4.2.patch
new file mode 100644
index 0000000..443ba74
--- /dev/null
+++ b/xsa110-4.3-and-4.2.patch
@@ -0,0 +1,156 @@
+x86emul: enforce privilege level restrictions when loading CS
+
+Privilege level checks were basically missing for the CS case, the
+only check that was done (RPL == DPL for nonconforming segments)
+was solely covering a single special case (return to non-conforming
+segment).
+
+Additionally in long mode the L bit set requires the D bit to be clear,
+as was recently pointed out for KVM by Nadav Amit
+<namit at cs.technion.ac.il>.
+
+Finally we also need to force the loaded selector's RPL to CPL (at
+least as long as lret/retf emulation doesn't support privilege level
+changes).
+
+This is XSA-110.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+Reviewed-by: Tim Deegan <tim at xen.org>
+
+--- a/xen/arch/x86/x86_emulate/x86_emulate.c
++++ b/xen/arch/x86/x86_emulate/x86_emulate.c
+@@ -1107,7 +1107,7 @@ realmode_load_seg(
+ static int
+ protmode_load_seg(
+     enum x86_segment seg,
+-    uint16_t sel,
++    uint16_t sel, bool_t is_ret,
+     struct x86_emulate_ctxt *ctxt,
+     const struct x86_emulate_ops *ops)
+ {
+@@ -1179,9 +1179,23 @@ protmode_load_seg(
+         /* Code segment? */
+         if ( !(desc.b & (1u<<11)) )
+             goto raise_exn;
+-        /* Non-conforming segment: check DPL against RPL. */
+-        if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) )
++        if ( is_ret
++             ? /*
++                * Really rpl < cpl, but our sole caller doesn't handle
++                * privilege level changes.
++                */
++               rpl != cpl || (desc.b & (1 << 10) ? dpl > rpl : dpl != rpl)
++             : desc.b & (1 << 10)
++               /* Conforming segment: check DPL against CPL. */
++               ? dpl > cpl
++               /* Non-conforming segment: check RPL and DPL against CPL. */
++               : rpl > cpl || dpl != cpl )
+             goto raise_exn;
++        /* 64-bit code segments (L bit set) must have D bit clear. */
++        if ( in_longmode(ctxt, ops) &&
++             (desc.b & (1 << 21)) && (desc.b & (1 << 22)) )
++            goto raise_exn;
++        sel = (sel ^ rpl) | cpl;
+         break;
+     case x86_seg_ss:
+         /* Writable data segment? */
+@@ -1246,7 +1260,7 @@ protmode_load_seg(
+ static int
+ load_seg(
+     enum x86_segment seg,
+-    uint16_t sel,
++    uint16_t sel, bool_t is_ret,
+     struct x86_emulate_ctxt *ctxt,
+     const struct x86_emulate_ops *ops)
+ {
+@@ -1255,7 +1269,7 @@ load_seg(
+         return X86EMUL_UNHANDLEABLE;
+ 
+     if ( in_protmode(ctxt, ops) )
+-        return protmode_load_seg(seg, sel, ctxt, ops);
++        return protmode_load_seg(seg, sel, is_ret, ctxt, ops);
+ 
+     return realmode_load_seg(seg, sel, ctxt, ops);
+ }
+@@ -1852,7 +1866,7 @@ x86_emulate(
+         if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+                               &dst.val, op_bytes, ctxt, ops)) != 0 )
+             goto done;
+-        if ( (rc = load_seg(src.val, (uint16_t)dst.val, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(src.val, dst.val, 0, ctxt, ops)) != 0 )
+             return rc;
+         break;
+ 
+@@ -2222,7 +2236,7 @@ x86_emulate(
+         enum x86_segment seg = decode_segment(modrm_reg);
+         generate_exception_if(seg == decode_segment_failed, EXC_UD, -1);
+         generate_exception_if(seg == x86_seg_cs, EXC_UD, -1);
+-        if ( (rc = load_seg(seg, (uint16_t)src.val, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(seg, src.val, 0, ctxt, ops)) != 0 )
+             goto done;
+         if ( seg == x86_seg_ss )
+             ctxt->retire.flags.mov_ss = 1;
+@@ -2303,7 +2317,7 @@ x86_emulate(
+                               &_regs.eip, op_bytes, ctxt)) )
+             goto done;
+ 
+-        if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
+             goto done;
+         _regs.eip = eip;
+         break;
+@@ -2526,7 +2540,7 @@ x86_emulate(
+         if ( (rc = read_ulong(src.mem.seg, src.mem.off + src.bytes,
+                               &sel, 2, ctxt, ops)) != 0 )
+             goto done;
+-        if ( (rc = load_seg(dst.val, (uint16_t)sel, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(dst.val, sel, 0, ctxt, ops)) != 0 )
+             goto done;
+         dst.val = src.val;
+         break;
+@@ -2600,7 +2614,7 @@ x86_emulate(
+                               &dst.val, op_bytes, ctxt, ops)) ||
+              (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes + offset),
+                               &src.val, op_bytes, ctxt, ops)) ||
+-             (rc = load_seg(x86_seg_cs, (uint16_t)src.val, ctxt, ops)) )
++             (rc = load_seg(x86_seg_cs, src.val, 1, ctxt, ops)) )
+             goto done;
+         _regs.eip = dst.val;
+         break;
+@@ -2647,7 +2661,7 @@ x86_emulate(
+         _regs.eflags &= mask;
+         _regs.eflags |= (uint32_t)(eflags & ~mask) | 0x02;
+         _regs.eip = eip;
+-        if ( (rc = load_seg(x86_seg_cs, (uint16_t)cs, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(x86_seg_cs, cs, 1, ctxt, ops)) != 0 )
+             goto done;
+         break;
+     }
+@@ -3277,7 +3291,7 @@ x86_emulate(
+         generate_exception_if(mode_64bit(), EXC_UD, -1);
+         eip = insn_fetch_bytes(op_bytes);
+         sel = insn_fetch_type(uint16_t);
+-        if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
++        if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
+             goto done;
+         _regs.eip = eip;
+         break;
+@@ -3590,7 +3604,7 @@ x86_emulate(
+                     goto done;
+             }
+ 
+-            if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
++            if ( (rc = load_seg(x86_seg_cs, sel, 0, ctxt, ops)) != 0 )
+                 goto done;
+             _regs.eip = dst.val;
+ 
+@@ -3671,7 +3685,7 @@ x86_emulate(
+         generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
+         generate_exception_if(!mode_ring0(), EXC_GP, 0);
+         if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr,
+-                            src.val, ctxt, ops)) != 0 )
++                            src.val, 0, ctxt, ops)) != 0 )
+             goto done;
+         break;
+ 


More information about the scm-commits mailing list