From 18c0da6ed7ec604b85bf3956062bd98ad2c298a7 Mon Sep 17 00:00:00 2001 From: Michael Young Date: Nov 18 2014 22:42:43 +0000 Subject: 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 --- 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 66ac195..b08057e 100644 --- a/xen.spec +++ b/xen.spec @@ -53,7 +53,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.4.1 -Release: 6%{?dist} +Release: 7%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -106,6 +106,9 @@ Patch25: xsa104.patch Patch26: xsa105.patch Patch27: xsa106.patch Patch28: xsa108.patch +Patch29: xsa109.patch +Patch30: xsa110.patch +Patch31: CVE-2014-0150.patch Patch99: xen.figs.disable.patch Patch100: xen-configure-xend.patch @@ -297,6 +300,9 @@ manage Xen virtual machines. %patch26 -p1 %patch27 -p1 %patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 %patch99 -p1 %patch100 -p1 @@ -899,6 +905,14 @@ rm -rf %{buildroot} %endif %changelog +* Tue Nov 18 2014 Michael Young - 4.4.1-7 +- 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 - 4.4.1-6 - Improper MSR range used for x2APIC emulation [XSA-108, CVE-2014-7188] (#1148465) diff --git a/xsa109.patch b/xsa109.patch new file mode 100644 index 0000000..0028b2f --- /dev/null +++ b/xsa109.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 +Acked-by: Tim Deegan + +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -3493,6 +3493,10 @@ long do_mmu_update( + { + p2m_type_t p2mt; + ++ rc = -EOPNOTSUPP; ++ if ( unlikely(paging_mode_refcounts(pt_owner)) ) ++ break; ++ + xsm_needed |= XSM_MMU_NORMAL_UPDATE; + if ( get_pte_flags(req.val) & _PAGE_PRESENT ) + { diff --git a/xsa110.patch b/xsa110.patch new file mode 100644 index 0000000..3e7479f --- /dev/null +++ b/xsa110.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 +. + +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 +Reviewed-by: Tim Deegan + +--- a/xen/arch/x86/x86_emulate/x86_emulate.c ++++ b/xen/arch/x86/x86_emulate/x86_emulate.c +@@ -1119,7 +1119,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) + { +@@ -1185,9 +1185,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? */ +@@ -1252,7 +1266,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) + { +@@ -1261,7 +1275,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); + } +@@ -2003,7 +2017,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; + +@@ -2357,7 +2371,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; +@@ -2438,7 +2452,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; +@@ -2662,7 +2676,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; +@@ -2736,7 +2750,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; +@@ -2785,7 +2799,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; + } +@@ -3415,7 +3429,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; +@@ -3714,7 +3728,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 = src.val; + +@@ -3781,7 +3795,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; +