diff -Nru xen-4.4.2/debian/changelog xen-4.4.2/debian/changelog --- xen-4.4.2/debian/changelog 2016-02-23 21:16:19.000000000 +0000 +++ xen-4.4.2/debian/changelog 2016-10-06 13:59:42.000000000 +0000 @@ -1,3 +1,75 @@ +xen (4.4.2-0ubuntu0.14.04.7) trusty-security; urgency=low + + * Applying Xen Security Advisories: + - CVE-2016-6258 / XSA-182 + * x86/pv: Remove unsafe bits from the mod_l?_entry() fastpath + - CVE-2016-5403 / XSA-184 + * virtio: error out if guest exceeds virtqueue size + - CVE-2016-7092 / XSA-185 + * x86/32on64: don't allow recursive page tables from L3 + - CVE-2016-7094 / XSA-187 + * x86/shadow: Avoid overflowing sh_ctxt->seg_reg[] + * x86/segment: Bounds check accesses to emulation ctxt->seg_reg[] + - CVE-2016-7154 / XSA-188 + * evtchn-fifo: prevent use after free + - CVE-2016-7777 / XSA-190 + * x86emul: honor guest CR0.TS and CR0.EM + + -- Stefan Bader Thu, 06 Oct 2016 15:56:51 +0200 + +xen (4.4.2-0ubuntu0.14.04.6) trusty-security; urgency=low + + * Applying Xen Security Advisories: + - CVE-2016-3158, CVE-2016-3159 / XSA-172 + * x86: fix information leak on AMD CPUs + - CVE-2016-3960 / XSA-173 + * x86: limit GFNs to 32 bits for shadowed superpages. + - CVE-2016-4962 / XSA-175 + * libxl: Record backend/frontend paths in /libxl/$DOMID + * libxl: Provide libxl__backendpath_parse_domid + * libxl: Do not trust frontend in libxl__devices_destroy + * libxl: Do not trust frontend in libxl__device_nextid + * libxl: Do not trust frontend for disk eject event + * libxl: Do not trust frontend for disk in getinfo + * libxl: Do not trust frontend for vtpm list + * libxl: Do not trust frontend for vtpm in getinfo + * libxl: Do not trust frontend for nic in libxl_devid_to_device_nic + * libxl: Do not trust frontend for nic in getinfo + * libxl: Cleanup: Have libxl__alloc_vdev use /libxl + * libxl: Document ~/serial/ correctly + - CVE-2016-4480 / XSA-176 + * x86/mm: fully honor PS bits in guest page table walks + - CVE-2016-4963 / XSA-178 + * libxl: Do not trust backend for vtpm in getinfo (except uuid) + * libxl: Do not trust backend for vtpm in getinfo (uuid) + * libxl: cdrom eject and insert: write to /libxl + * libxl: Do not trust backend for disk eject vdev + * libxl: Do not trust backend for disk; fix driver domain disks list + * libxl: Do not trust backend for disk in getinfo + * libxl: Do not trust backend for cdrom insert + * libxl: Rename libxl__device_{nic,channel}_from_xs_be to _from_xenstore + * libxl: Rename READ_BACKEND to READ_LIBXLDEV + * libxl: Have READ_LIBXLDEV use libxl_path rather than be_path + * libxl: Do not trust backend in nic getinfo + * libxl: Do not trust backend for nic in devid_to_device + * libxl: Do not trust backend for nic in list + * libxl: Cleanup: use libxl__backendpath_parse_domid in + libxl__device_disk_from_xs_be + * libxl: Fix NULL pointer due to XSA-178 fix wrong XS nodename + - CVE-2016-3710 / XSA-179 (qemu traditional) + * vga: fix banked access bounds checking + * vga: add vbe_enabled() helper + * vga: factor out vga register setup + * vga: update vga register setup on vbe changes + * vga: make sure vga register setup for vbe stays intact + - CVE-2014-3672 / XSA-180 (qemu traditional) + * main loop: Big hammer to fix logfile disk DoS in Xen setups + - CVE-2016-5242 / XSA-181 + * xen/arm: Don't free p2m->first_level in p2m_teardown() before + it has been allocated + + -- Stefan Bader Mon, 06 Jun 2016 14:17:35 +0200 + xen (4.4.2-0ubuntu0.14.04.5) trusty-security; urgency=low * Applying Xen Security Advisories: diff -Nru xen-4.4.2/debian/patches/series xen-4.4.2/debian/patches/series --- xen-4.4.2/debian/patches/series 2016-02-19 13:24:20.000000000 +0000 +++ xen-4.4.2/debian/patches/series 2016-10-06 15:51:25.000000000 +0000 @@ -142,3 +142,47 @@ xsa169.patch xsa170-4.5.patch xsa154-4.4.patch +xsa172.patch +xsa173-4.4.patch +xsa175-4.4-0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch +xsa175-4.4-0002-libxl-Provide-libxl__backendpath_parse_domid.patch +xsa175-4.4-0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch +xsa175-4.4-0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch +xsa175-4.4-0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch +xsa175-4.4-0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch +xsa175-4.4-0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch +xsa175-4.4-0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch +xsa175-4.4-0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch +xsa175-4.4-0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch +xsa175-4.4-0011-libxl-Cleanup-Have-libxl__alloc_vdev-use-libxl.patch +xsa175-4.4-0012-libxl-Document-serial-correctly.patch +xsa176.patch +xsa178-xen4.4-0001-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-excep.patch +xsa178-xen4.4-0002-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-uuid.patch +xsa178-xen4.4-0003-libxl-cdrom-eject-and-insert-write-to-libxl.patch +xsa178-xen4.4-0004-libxl-Do-not-trust-backend-for-disk-eject-vdev.patch +xsa178-xen4.4-0005-libxl-Do-not-trust-backend-for-disk-fix-driver-domai.patch +xsa178-xen4.4-0006-libxl-Do-not-trust-backend-for-disk-in-getinfo.patch +xsa178-xen4.4-0007-libxl-Do-not-trust-backend-for-cdrom-insert.patch +xsa178-xen4.4-0008-libxl-Rename-libxl__device_nic_from_xs_be-to-_from_x.patch +xsa178-xen4.4-0009-libxl-Rename-READ_BACKEND-to-READ_LIBXLDEV.patch +xsa178-xen4.4-0010-libxl-Have-READ_LIBXLDEV-use-libxl_path-rather-than-.patch +xsa178-xen4.4-0011-libxl-Do-not-trust-backend-in-nic-getinfo.patch +xsa178-xen4.4-0012-libxl-Do-not-trust-backend-for-nic-in-devid_to_devic.patch +xsa178-xen4.4-0013-libxl-Do-not-trust-backend-for-nic-in-list.patch +xsa178-xen4.4-0014-libxl-Cleanup-use-libxl__backendpath_parse_domid-in-.patch +xsa178-xen4.4-0015-libxl-Fix-NULL-pointer-due-to-XSA-178-fix-wrong-XS-n.patch +xsa179-qemut-4.4-0001-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch +xsa179-qemut-4.4-0002-vga-add-vbe_enabled-helper.patch +xsa179-qemut-4.4-0003-vga-factor-out-vga-register-setup.patch +xsa179-qemut-4.4-0004-vga-update-vga-register-setup-on-vbe-changes.patch +xsa179-qemut-4.4-0005-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch +xsa180-qemut.patch +xsa181-4.4.patch +xsa182-4.5.patch +xsa184-qemut-master.patch +xsa185.patch +xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch +xsa187-4.4-0002-x86-segment-Bounds-check-accesses-to-emulation-ctx.patch +xsa188.patch +xsa190-4.5.patch diff -Nru xen-4.4.2/debian/patches/xsa172.patch xen-4.4.2/debian/patches/xsa172.patch --- xen-4.4.2/debian/patches/xsa172.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa172.patch 2016-06-06 12:14:49.000000000 +0000 @@ -0,0 +1,39 @@ +x86: fix information leak on AMD CPUs + +The fix for XSA-52 was wrong, and so was the change synchronizing that +new behavior to the FXRSTOR logic: AMD's manuals explictly state that +writes to the ES bit are ignored, and it instead gets calculated from +the exception and mask bits (it gets set whenever there is an unmasked +exception, and cleared otherwise). Hence we need to follow that model +in our workaround. + +This is XSA-172. + +The first hunk (xen/arch/x86/i387.c:fpu_fxrstor) is CVE-2016-3159. +The second hunk (xen/arch/x86/xstate.c:xrstor) is CVE-2016-3158. + +Signed-off-by: Jan Beulich +Reviewed-by: Andrew Cooper + +--- a/xen/arch/x86/i387.c ++++ b/xen/arch/x86/i387.c +@@ -49,7 +49,7 @@ static inline void fpu_fxrstor(struct vc + * sometimes new user value. Both should be ok. Use the FPU saved + * data block as a safe address because it should be in L1. + */ +- if ( !(fpu_ctxt->fsw & 0x0080) && ++ if ( !(fpu_ctxt->fsw & ~fpu_ctxt->fcw & 0x003f) && + boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) + { + asm volatile ( "fnclex\n\t" +--- a/xen/arch/x86/xstate.c ++++ b/xen/arch/x86/xstate.c +@@ -344,7 +344,7 @@ void xrstor(struct vcpu *v, uint64_t mas + * data block as a safe address because it should be in L1. + */ + if ( (mask & ptr->xsave_hdr.xstate_bv & XSTATE_FP) && +- !(ptr->fpu_sse.fsw & 0x0080) && ++ !(ptr->fpu_sse.fsw & ~ptr->fpu_sse.fcw & 0x003f) && + boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) + asm volatile ( "fnclex\n\t" /* clear exceptions */ + "ffree %%st(7)\n\t" /* clear stack tag */ diff -Nru xen-4.4.2/debian/patches/xsa173-4.4.patch xen-4.4.2/debian/patches/xsa173-4.4.patch --- xen-4.4.2/debian/patches/xsa173-4.4.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa173-4.4.patch 2016-06-06 12:15:09.000000000 +0000 @@ -0,0 +1,251 @@ +commit 5893f9ea852f428e7120a4f3184a20deeb145d91 +Author: Tim Deegan +Date: Wed Mar 16 17:05:25 2016 +0000 + + x86: limit GFNs to 32 bits for shadowed superpages. + + Superpage shadows store the shadowed GFN in the backpointer field, + which for non-BIGMEM builds is 32 bits wide. Shadowing a superpage + mapping of a guest-physical address above 2^44 would lead to the GFN + being truncated there, and a crash when we come to remove the shadow + from the hash table. + + Track the valid width of a GFN for each guest, including reporting it + through CPUID, and enforce it in the shadow pagetables. Set the + maximum witth to 32 for guests where this truncation could occur. + + This is XSA-173. + + Signed-off-by: Tim Deegan + Signed-off-by: Jan Beulich + +Reported-by: Ling Liu +diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c +index 4221826..f436f91 100644 +--- a/xen/arch/x86/cpu/common.c ++++ b/xen/arch/x86/cpu/common.c +@@ -37,6 +37,7 @@ integer_param("cpuid_mask_ext_edx", opt_cpuid_mask_ext_edx); + struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; + + unsigned int paddr_bits __read_mostly = 36; ++unsigned int hap_paddr_bits __read_mostly = 36; + + /* + * Default host IA32_CR_PAT value to cover all memory types. +@@ -195,7 +196,7 @@ static void __init early_cpu_detect(void) + + static void __cpuinit generic_identify(struct cpuinfo_x86 *c) + { +- u32 tfms, xlvl, capability, excap, ebx; ++ u32 tfms, xlvl, capability, excap, eax, ebx; + + /* Get vendor name */ + cpuid(0x00000000, &c->cpuid_level, +@@ -230,8 +231,11 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) + } + if ( xlvl >= 0x80000004 ) + get_model_name(c); /* Default name */ +- if ( xlvl >= 0x80000008 ) +- paddr_bits = cpuid_eax(0x80000008) & 0xff; ++ if ( xlvl >= 0x80000008 ) { ++ eax = cpuid_eax(0x80000008); ++ paddr_bits = eax & 0xff; ++ hap_paddr_bits = ((eax >> 16) & 0xff) ?: paddr_bits; ++ } + } + + /* Might lift BIOS max_leaf=3 limit. */ +diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c +index f3f6c61..a4bfb90 100644 +--- a/xen/arch/x86/hvm/hvm.c ++++ b/xen/arch/x86/hvm/hvm.c +@@ -2966,8 +2966,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, + break; + + case 0x80000008: +- count = cpuid_eax(0x80000008); +- count = (count >> 16) & 0xff ?: count & 0xff; ++ count = d->arch.paging.gfn_bits + PAGE_SHIFT; + if ( (*eax & 0xff) > count ) + *eax = (*eax & ~0xff) | count; + +diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c +index 70460b6..09511f0 100644 +--- a/xen/arch/x86/mm/guest_walk.c ++++ b/xen/arch/x86/mm/guest_walk.c +@@ -94,6 +94,12 @@ void *map_domain_gfn(struct p2m_domain *p2m, gfn_t gfn, mfn_t *mfn, + struct page_info *page; + void *map; + ++ if ( gfn_x(gfn) >> p2m->domain->arch.paging.gfn_bits ) ++ { ++ *rc = _PAGE_INVALID_BIT; ++ return NULL; ++ } ++ + /* Translate the gfn, unsharing if shared */ + page = get_page_from_gfn_p2m(p2m->domain, p2m, gfn_x(gfn), p2mt, NULL, + q); +@@ -294,20 +300,8 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, + flags &= ~_PAGE_PAT; + + if ( gfn_x(start) & GUEST_L2_GFN_MASK & ~0x1 ) +- { +-#if GUEST_PAGING_LEVELS == 2 +- /* +- * Note that _PAGE_INVALID_BITS is zero in this case, yielding a +- * no-op here. +- * +- * Architecturally, the walk should fail if bit 21 is set (others +- * aren't being checked at least in PSE36 mode), but we'll ignore +- * this here in order to avoid specifying a non-natural, non-zero +- * _PAGE_INVALID_BITS value just for that case. +- */ +-#endif + rc |= _PAGE_INVALID_BITS; +- } ++ + /* Increment the pfn by the right number of 4k pages. + * Mask out PAT and invalid bits. */ + start = _gfn((gfn_x(start) & ~GUEST_L2_GFN_MASK) + +@@ -390,5 +384,11 @@ set_ad: + put_page(mfn_to_page(mfn_x(gw->l1mfn))); + } + ++ /* If this guest has a restricted physical address space then the ++ * target GFN must fit within it. */ ++ if ( !(rc & _PAGE_PRESENT) ++ && gfn_x(guest_l1e_get_gfn(gw->l1e)) >> d->arch.paging.gfn_bits ) ++ rc |= _PAGE_INVALID_BITS; ++ + return rc; + } +diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c +index c06369b..ccc4174 100644 +--- a/xen/arch/x86/mm/hap/hap.c ++++ b/xen/arch/x86/mm/hap/hap.c +@@ -428,6 +428,7 @@ static void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn) + void hap_domain_init(struct domain *d) + { + INIT_PAGE_LIST_HEAD(&d->arch.paging.hap.freelist); ++ d->arch.paging.gfn_bits = hap_paddr_bits - PAGE_SHIFT; + } + + /* return 0 for success, -errno for failure */ +diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c +index 90ba4d6..06a04ad 100644 +--- a/xen/arch/x86/mm/shadow/common.c ++++ b/xen/arch/x86/mm/shadow/common.c +@@ -48,6 +48,16 @@ void shadow_domain_init(struct domain *d, unsigned int domcr_flags) + INIT_PAGE_LIST_HEAD(&d->arch.paging.shadow.freelist); + INIT_PAGE_LIST_HEAD(&d->arch.paging.shadow.pinned_shadows); + ++ d->arch.paging.gfn_bits = paddr_bits - PAGE_SHIFT; ++#ifndef CONFIG_BIGMEM ++ /* ++ * Shadowed superpages store GFNs in 32-bit page_info fields. ++ * Note that we cannot use guest_supports_superpages() here. ++ */ ++ if ( !is_pv_domain(d) || opt_allow_superpage ) ++ d->arch.paging.gfn_bits = 32; ++#endif ++ + /* Use shadow pagetables for log-dirty support */ + paging_log_dirty_init(d, shadow_enable_log_dirty, + shadow_disable_log_dirty, shadow_clean_dirty_bitmap); +diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c +index 0f499bf..6c88d4e 100644 +--- a/xen/arch/x86/mm/shadow/multi.c ++++ b/xen/arch/x86/mm/shadow/multi.c +@@ -527,7 +527,8 @@ _sh_propagate(struct vcpu *v, + ASSERT(GUEST_PAGING_LEVELS > 3 || level != 3); + + /* Check there's something for the shadows to map to */ +- if ( !p2m_is_valid(p2mt) && !p2m_is_grant(p2mt) ) ++ if ( (!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ++ || gfn_x(target_gfn) >> d->arch.paging.gfn_bits ) + { + *sp = shadow_l1e_empty(); + goto done; +diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h +index 7dfbbcb..a03fc2e 100644 +--- a/xen/include/asm-x86/domain.h ++++ b/xen/include/asm-x86/domain.h +@@ -187,6 +187,9 @@ struct paging_domain { + /* log dirty support */ + struct log_dirty_domain log_dirty; + ++ /* Number of valid bits in a gfn. */ ++ unsigned int gfn_bits; ++ + /* preemption handling */ + struct { + const struct domain *dom; +diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h +index d2a8250..d95f835 100644 +--- a/xen/include/asm-x86/guest_pt.h ++++ b/xen/include/asm-x86/guest_pt.h +@@ -220,15 +220,17 @@ guest_supports_nx(struct vcpu *v) + } + + +-/* Some bits are invalid in any pagetable entry. */ +-#if GUEST_PAGING_LEVELS == 2 +-#define _PAGE_INVALID_BITS (0) +-#elif GUEST_PAGING_LEVELS == 3 +-#define _PAGE_INVALID_BITS \ +- get_pte_flags(((1ull<<63) - 1) & ~((1ull< +Date: Mon, 16 May 2016 16:44:31 +0100 +Subject: [PATCH 01/10] libxl: Record backend/frontend paths in /libxl/$DOMID + +This gives us a record of all the backends we have set up for a +domain, which is separate from the frontends in + /local/domain/$DOMID/device. + +In particular: + +1. A guest has write permission for the frontend path: + /local/domain/$DOMID/device/$KIND/$DEVID +which means that the guest can completely delete the frontend. +(They can't recreate it because they don't have write permission +on the containing directory.) + +2. A guest has write permission for the backend path recorded in the +frontend, ie, it can write to + /local/domain/$DOMID/device/$KIND/$DEVID/backend +which means that the guest can break the association between +frontend and backend. + +So we can't rely on iterating over the frontends to find all the +backends, or examining a frontend to discover how a device is +configured. + +So, have libxl__device_generic_add record the frontend and backend +paths in /libxl/$DOMID/device, and have libxl__device_destroy remove +them again. + +Create the containing directory /libxl/GUEST/device in +libxl__domain_make. The already existing xs_rm in devices_destroy_cb +will take care of removing it. + +This is part of XSA-175. + +Backport note: Backported over 7472ced, which fixes a bug in driver +domain teardown. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- +v2: Correct actual path computation (!) +v3: Correct actual path computation - really this time (!) +--- + docs/misc/xenstore-paths.markdown | 15 +++++++++++++++ + tools/libxl/libxl_create.c | 2 ++ + tools/libxl/libxl_device.c | 34 +++++++++++++++++++++++++++++++++- + tools/libxl/libxl_internal.h | 1 + + 4 files changed, 51 insertions(+), 1 deletion(-) + +diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown +index 70ab7f4..e018b55 100644 +--- a/docs/misc/xenstore-paths.markdown ++++ b/docs/misc/xenstore-paths.markdown +@@ -381,6 +381,21 @@ The guest's virtual time offset from UTC in seconds. + + ### libxl Specific Paths + ++#### /libxl/$DOMID/device/$KIND/$DEVID ++ ++Created by libxl for every frontend/backend pair created for $DOMID. ++Used by libxl for enumeration and management of the device. ++ ++#### /libxl/$DOMID/device/$KIND/$DEVID/frontend ++ ++Path in xenstore to the frontend, normally ++/local/domain/$DOMID/device/$KIND/$DEVID ++ ++#### /libxl/$DOMID/device/$KIND/$DEVID/backend ++ ++Path in xenstore to the backend, normally ++/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID ++ + #### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL] + + The device model version for a domain. +diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c +index 5292c15..0e26666 100644 +--- a/tools/libxl/libxl_create.c ++++ b/tools/libxl/libxl_create.c +@@ -528,6 +528,8 @@ retry_transaction: + + xs_rm(ctx->xsh, t, libxl_path); + libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm)); ++ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path), ++ noperm, ARRAY_SIZE(noperm)); + + xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); + rc = libxl__domain_rename(gc, *domid, 0, info->name, t); +diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c +index 29ed547..e9d2424 100644 +--- a/tools/libxl/libxl_device.c ++++ b/tools/libxl/libxl_device.c +@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device) + device->domid, device->devid); + } + ++char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device) ++{ ++ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid); ++ ++ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path, ++ libxl__device_kind_to_string(device->kind), ++ device->devid); ++} ++ + int libxl__parse_backend_path(libxl__gc *gc, + const char *path, + libxl__device *dev) +@@ -87,14 +96,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t, + libxl__device *device, char **bents, char **fents, char **ro_fents) + { + libxl_ctx *ctx = libxl__gc_owner(gc); +- char *frontend_path, *backend_path; ++ char *frontend_path, *backend_path, *libxl_path; + struct xs_permissions frontend_perms[2]; + struct xs_permissions ro_frontend_perms[2]; + struct xs_permissions backend_perms[2]; + int create_transaction = t == XBT_NULL; ++ int rc; + + frontend_path = libxl__device_frontend_path(gc, device); + backend_path = libxl__device_backend_path(gc, device); ++ libxl_path = libxl__device_libxl_path(gc, device); + + frontend_perms[0].id = device->domid; + frontend_perms[0].perms = XS_PERM_NONE; +@@ -109,8 +120,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t, + retry_transaction: + if (create_transaction) + t = xs_transaction_start(ctx->xsh); ++ + /* FIXME: read frontend_path and check state before removing stuff */ + ++ rc = libxl__xs_rm_checked(gc, t, libxl_path); ++ if (rc) goto out; ++ ++ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path), ++ frontend_path); ++ if (rc) goto out; ++ ++ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path), ++ backend_path); ++ if (rc) goto out; ++ ++ /* xxx much of this function lacks error checks! */ ++ + if (fents || ro_fents) { + xs_rm(ctx->xsh, t, frontend_path); + xs_mkdir(ctx->xsh, t, frontend_path); +@@ -156,6 +181,11 @@ retry_transaction: + } + } + return 0; ++ ++ out: ++ if (create_transaction && t) ++ libxl__xs_transaction_abort(gc, &t); ++ return rc; + } + + typedef struct { +@@ -552,6 +582,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev) + { + const char *be_path = libxl__device_backend_path(gc, dev); + const char *fe_path = libxl__device_frontend_path(gc, dev); ++ const char *libxl_path = libxl__device_libxl_path(gc, dev); + const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params"); + const char *tapdisk_params; + xs_transaction_t t = 0; +@@ -576,6 +607,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev) + */ + libxl__xs_path_cleanup(gc, t, fe_path); + libxl__xs_path_cleanup(gc, t, be_path); ++ libxl__xs_path_cleanup(gc, t, libxl_path); + } else if (dev->backend_domid == domid) { + /* + * The driver domain is in charge for removing what it can +diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h +index f6d469b..801e95d 100644 +--- a/tools/libxl/libxl_internal.h ++++ b/tools/libxl/libxl_internal.h +@@ -968,6 +968,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t, + libxl__device *device, char **bents, char **fents, char **ro_fents); + _hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device); + _hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device); ++_hidden char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device); + _hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path, + libxl__device *dev); + _hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev); +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0002-libxl-Provide-libxl__backendpath_parse_domid.patch xen-4.4.2/debian/patches/xsa175-4.4-0002-libxl-Provide-libxl__backendpath_parse_domid.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0002-libxl-Provide-libxl__backendpath_parse_domid.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0002-libxl-Provide-libxl__backendpath_parse_domid.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,62 @@ +From 35a740847bea0a2aede72de7b2b8b49eef36e4eb Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 27 Apr 2016 16:34:19 +0100 +Subject: [PATCH 02/10] libxl: Provide libxl__backendpath_parse_domid + +Multiple places in libxl need to figure out the backend domid of a +device. This can be discovered easily by looking at the backend path, +which always starts /local/domain/$backend_domid/. + +There are no call sites yet. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl_device.c | 15 +++++++++++++++ + tools/libxl/libxl_internal.h | 2 ++ + 2 files changed, 17 insertions(+) + +diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c +index e9d2424..b500264 100644 +--- a/tools/libxl/libxl_device.c ++++ b/tools/libxl/libxl_device.c +@@ -270,6 +270,21 @@ static int disk_try_backend(disk_try_backend_args *a, + return 0; + } + ++int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path, ++ libxl_domid *domid_out) { ++ int r; ++ unsigned int domid_sc; ++ char delim_sc; ++ ++ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc); ++ if (!(r==2 && delim_sc=='/')) { ++ LOG(ERROR, "internal error: backend path %s unparseable!", be_path); ++ return ERROR_FAIL; ++ } ++ *domid_out = domid_sc; ++ return 0; ++} ++ + int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) { + libxl_disk_backend ok; + disk_try_backend_args a; +diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h +index 801e95d..3fc9997 100644 +--- a/tools/libxl/libxl_internal.h ++++ b/tools/libxl/libxl_internal.h +@@ -574,6 +574,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t, + + _hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid); + ++_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path, ++ libxl_domid *domid_out); + + /*----- "checked" xenstore access functions -----*/ + /* Each of these functions will check that it succeeded; if it +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch xen-4.4.2/debian/patches/xsa175-4.4-0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,77 @@ +From ef216637a72ce30661d28a47ccc7464869baa398 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 18:39:36 +0100 +Subject: [PATCH 03/10] libxl: Do not trust frontend in libxl__devices_destroy + +We need to enumerate the devices we have provided to a domain, without +trusting the guest-writeable (or, at least, guest-deletable) frontend +paths. + +Instead, enumerate via, and read the backend path from, /libxl. + +The console /libxl path is regular, so the special case for console 0 +is not relevant any more: /libxl/GUEST/device/console/0 will be found, +and then libxl__device_destroy will DTRT to the right frontend path. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl_device.c | 22 +++------------------- + 1 file changed, 3 insertions(+), 19 deletions(-) + +diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c +index b500264..e7650d0 100644 +--- a/tools/libxl/libxl_device.c ++++ b/tools/libxl/libxl_device.c +@@ -665,7 +665,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) + libxl__multidev_begin(ao, multidev); + multidev->callback = devices_remove_callback; + +- path = GCSPRINTF("/local/domain/%d/device", domid); ++ path = GCSPRINTF("/libxl/%d/device", domid); + kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds); + if (!kinds) { + if (errno != ENOENT) { +@@ -678,12 +678,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) + if (libxl__device_kind_from_string(kinds[i], &kind)) + continue; + +- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]); ++ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]); + devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries); + if (!devs) + continue; + for (j = 0; j < num_dev_xsentries; j++) { +- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend", ++ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend", + domid, kinds[i], devs[j]); + path = libxl__xs_read(gc, XBT_NULL, path); + GCNEW(dev); +@@ -708,22 +708,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) + } + } + +- /* console 0 frontend directory is not under /local/domain//device */ +- path = GCSPRINTF("/local/domain/%d/console/backend", domid); +- path = libxl__xs_read(gc, XBT_NULL, path); +- GCNEW(dev); +- if (path && strcmp(path, "") && +- libxl__parse_backend_path(gc, path, dev) == 0) { +- dev->domid = domid; +- dev->kind = LIBXL__DEVICE_KIND_CONSOLE; +- dev->devid = 0; +- +- /* Currently console devices can be destroyed synchronously by just +- * removing xenstore entries, this is what libxl__device_destroy does. +- */ +- libxl__device_destroy(gc, dev); +- } +- + out: + libxl__multidev_prepared(egc, multidev, rc); + } +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch xen-4.4.2/debian/patches/xsa175-4.4-0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,43 @@ +From 90f14dc5c68f52baeef9722090695a166c7e083d Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 15:30:32 +0100 +Subject: [PATCH 04/10] libxl: Do not trust frontend in libxl__device_nextid + +When selecting the devid for a new device, we should look in +/libxl/device for existing devices, not in the frontend area. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index e2a5be3..b52e63e 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1743,15 +1743,16 @@ out: + /* common function to get next device id */ + static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device) + { +- char *dompath, **l; ++ char *libxl_dom_path, **l; + unsigned int nb; + int nextid = -1; + +- if (!(dompath = libxl__xs_get_dompath(gc, domid))) ++ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid))) + return nextid; + + l = libxl__xs_directory(gc, XBT_NULL, +- GCSPRINTF("%s/device/%s", dompath, device), &nb); ++ GCSPRINTF("%s/device/%s", libxl_dom_path, device), ++ &nb); + if (l == NULL || nb == 0) + nextid = 0; + else +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch xen-4.4.2/debian/patches/xsa175-4.4-0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,104 @@ +From d84e538d96525f75fc0aa7d0ebe3cd194186d0d4 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 27 Apr 2016 16:08:49 +0100 +Subject: [PATCH 05/10] libxl: Do not trust frontend for disk eject event + +Use the /libxl path for interpreting disk eject watch events: do not +read the backend path out of the frontend. Instead, use the version +in /libxl. That avoids us relying on the guest-modifiable +$frontend/backend pointer. + +To implement this we store the path + /libxl/$guest/device/vbd/$devid/backend +in the evgen structure. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 28 ++++++++++++++++++++++------ + tools/libxl/libxl_internal.h | 2 +- + 2 files changed, 23 insertions(+), 7 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index b52e63e..f101334 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1141,9 +1141,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w, + const char *wpath, const char *epath) { + EGC_GC; + libxl_evgen_disk_eject *evg = (void*)w; +- char *backend; ++ const char *backend; + char *value; + char backend_type[BACKEND_STRING_SIZE+1]; ++ int rc; + + value = libxl__xs_read(gc, XBT_NULL, wpath); + +@@ -1159,9 +1160,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w, + libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user); + libxl_device_disk *disk = &ev->u.disk_eject.disk; + +- backend = libxl__xs_read(gc, XBT_NULL, +- libxl__sprintf(gc, "%.*s/backend", +- (int)strlen(wpath)-6, wpath)); ++ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend); ++ if (rc) { ++ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path", ++ errno, LIBXL_EVENT_TYPE_DISK_EJECT); ++ return; ++ } ++ if (!backend) { ++ /* device has been removed, not simply ejected */ ++ return; ++ } + + sscanf(backend, + "/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE) +@@ -1210,11 +1218,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid, + if (!domid) + domid = guest_domid; + +- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject", ++ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL); ++ ++ path = GCSPRINTF("%s/device/vbd/%d/eject", + libxl__xs_get_dompath(gc, domid), +- libxl__device_disk_dev_number(vdev, NULL, NULL)); ++ devid); + if (!path) { rc = ERROR_NOMEM; goto out; } + ++ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d", ++ libxl__xs_libxl_path(gc, domid), ++ devid); ++ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path); ++ + rc = libxl__ev_xswatch_register(gc, &evg->watch, + disk_eject_xswatch_callback, path); + if (rc) goto out; +@@ -1241,6 +1256,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) { + libxl__ev_xswatch_deregister(gc, &evg->watch); + + free(evg->vdev); ++ free(evg->be_ptr_path); + free(evg); + + CTX_UNLOCK; +diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h +index 3fc9997..8128e76 100644 +--- a/tools/libxl/libxl_internal.h ++++ b/tools/libxl/libxl_internal.h +@@ -257,7 +257,7 @@ struct libxl__evgen_disk_eject { + uint32_t domid; + LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry; + libxl_ev_user user; +- char *vdev; ++ char *vdev, *be_ptr_path; + }; + _hidden void + libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*); +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch xen-4.4.2/debian/patches/xsa175-4.4-0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,79 @@ +From 3d1d7473c756d79e464600cee370c8759bd20f89 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 19:21:51 +0100 +Subject: [PATCH 06/10] libxl: Do not trust frontend for disk in getinfo + +* Rename the frontend variable to `fe_path' to check we caught them all +* Read the backend path from /libxl, rather than from the frontend +* Parse the backend domid from the backend path, rather than reading it + from the frontend (and add the appropriate error path and initialisation) + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index f101334..18f9f0a 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2449,27 +2449,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_disk *disk, libxl_diskinfo *diskinfo) + { + GC_INIT(ctx); +- char *dompath, *diskpath; ++ char *dompath, *fe_path, *libxl_path; + char *val; ++ int rc; ++ ++ diskinfo->backend = NULL; + + dompath = libxl__xs_get_dompath(gc, domid); + diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL); + + /* tap devices entries in xenstore are written as vbd devices. */ +- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid); ++ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid); ++ libxl_path = GCSPRINTF("%s/device/vbd/%d", ++ libxl__xs_libxl_path(gc, domid), diskinfo->devid); + diskinfo->backend = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/backend", diskpath), NULL); ++ GCSPRINTF("%s/backend", libxl_path), NULL); + if (!diskinfo->backend) { + GC_FREE; + return ERROR_FAIL; + } +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath)); +- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath)); ++ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend, ++ &diskinfo->backend_id); ++ if (rc) goto out; ++ ++ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path)); + diskinfo->state = val ? strtoul(val, NULL, 10) : -1; +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath)); ++ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path)); + diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1; +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath)); ++ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path)); + diskinfo->rref = val ? strtoul(val, NULL, 10) : -1; + diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL, + libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL); +@@ -2478,6 +2485,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, + + GC_FREE; + return 0; ++ ++ out: ++ free(diskinfo->backend); ++ return rc; + } + + int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch xen-4.4.2/debian/patches/xsa175-4.4-0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,67 @@ +From 44aadb912061fc75e41fceb00c67b8d222a2c7c4 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 15:58:32 +0100 +Subject: [PATCH 07/10] libxl: Do not trust frontend for vtpm list + +libxl_device_vtpm_list needs to enumerate and identify devices without +trusting frontend-controlled data. So + +* Use the /libxl path to enumerate vtpms. +* Use the /libxl path to find the corresponding backends. +* Parse the backend path to find the backend domid. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 18f9f0a..0886d92 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1879,14 +1879,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n + GC_INIT(ctx); + + libxl_device_vtpm* vtpms = NULL; +- char* fe_path = NULL; ++ char *libxl_path; + char** dir = NULL; + unsigned int ndirs = 0; ++ int rc; + + *num = 0; + +- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid)); +- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs); ++ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid)); ++ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs); + if (dir && ndirs) { + vtpms = malloc(sizeof(*vtpms) * ndirs); + libxl_device_vtpm* vtpm; +@@ -1895,16 +1896,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n + char* tmp; + const char* be_path = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/%s/backend", +- fe_path, *dir)); ++ libxl_path, *dir)); + + libxl_device_vtpm_init(vtpm); + + vtpm->devid = atoi(*dir); + +- tmp = libxl__xs_read(gc, XBT_NULL, +- GCSPRINTF("%s/%s/backend-id", +- fe_path, *dir)); +- vtpm->backend_domid = atoi(tmp); ++ rc = libxl__backendpath_parse_domid(gc, be_path, ++ &vtpm->backend_domid); ++ if (rc) return NULL; + + tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path)); + if (tmp) { +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch xen-4.4.2/debian/patches/xsa175-4.4-0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,61 @@ +From 593d796c753fea1c4cdc365273de777aff798fe9 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 16:00:20 +0100 +Subject: [PATCH 08/10] libxl: Do not trust frontend for vtpm in getinfo + +libxl_device_vtpm_getinfo needs to examine devices without trusting +frontend-controlled data. So: + +* Use /libxl to find the backend path. +* Parse the backend path to find the backend domid, rather than + reading it from the frontend. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 0886d92..a0aeb50 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1928,7 +1928,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + libxl_vtpminfo *vtpminfo) + { + GC_INIT(ctx); +- char *dompath, *vtpmpath; ++ char *libxl_path, *dompath, *vtpmpath; + char *val; + int rc = 0; + +@@ -1937,8 +1937,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + vtpminfo->devid = vtpm->devid; + + vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid); ++ libxl_path = GCSPRINTF("%s/device/vtpm/%d", ++ libxl__xs_libxl_path(gc, domid), vtpminfo->devid); + vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL, +- GCSPRINTF("%s/backend", vtpmpath), NULL); ++ GCSPRINTF("%s/backend", libxl_path), NULL); + if (!vtpminfo->backend) { + goto err; + } +@@ -1946,9 +1948,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + goto err; + } + +- val = libxl__xs_read(gc, XBT_NULL, +- GCSPRINTF("%s/backend-id", vtpmpath)); +- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1; ++ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend, ++ &vtpminfo->backend_id); ++ if (rc) goto exit; + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/state", vtpmpath)); +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch xen-4.4.2/debian/patches/xsa175-4.4-0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,47 @@ +From a7fb7be6b7a14e8ca5ab0609c49b06545d6772bf Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 15:52:53 +0100 +Subject: [PATCH 09/10] libxl: Do not trust frontend for nic in + libxl_devid_to_device_nic + +Find the backend by reading the pointer in /libxl rather than in the +guest's frontend area. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index a0aeb50..7a8faba 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3066,17 +3066,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_nic *nic) + { + GC_INIT(ctx); +- char *dompath, *path; ++ char *libxl_dom_path, *path; + int rc = ERROR_FAIL; + + libxl_device_nic_init(nic); +- dompath = libxl__xs_get_dompath(gc, domid); +- if (!dompath) ++ libxl_dom_path = libxl__xs_libxl_path(gc, domid); ++ if (!libxl_dom_path) + goto out; + + path = libxl__xs_read(gc, XBT_NULL, +- libxl__sprintf(gc, "%s/device/vif/%d/backend", +- dompath, devid)); ++ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path, ++ devid)); + if (!path) + goto out; + +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch xen-4.4.2/debian/patches/xsa175-4.4-0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch 2016-06-06 12:16:07.000000000 +0000 @@ -0,0 +1,73 @@ +From e4c0f9b55819194a501e3ecae6b12188a2db1d01 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 16:31:07 +0100 +Subject: [PATCH 10/10] libxl: Do not trust frontend for nic in getinfo + +libxl_device_nic_getinfo needs to examine devices without trusting +frontend-controlled data. So: + +* Use /libxl to find the backend path. +* Parse the backend path to find the backend domid, rather than + reading it from the frontend. + +This is part of XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- + tools/libxl/libxl.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 7a8faba..c794d3a 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3155,22 +3155,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_nic *nic, libxl_nicinfo *nicinfo) + { + GC_INIT(ctx); +- char *dompath, *nicpath; ++ char *dompath, *nicpath, *libxl_path; + char *val; ++ int rc; + + dompath = libxl__xs_get_dompath(gc, domid); + nicinfo->devid = nic->devid; + +- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid); ++ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid); ++ libxl_path = GCSPRINTF("%s/device/vif/%d", ++ libxl__xs_libxl_path(gc, domid), nicinfo->devid); + nicinfo->backend = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/backend", nicpath), NULL); ++ GCSPRINTF("%s/backend", libxl_path), NULL); + if (!nicinfo->backend) { + GC_FREE; + return ERROR_FAIL; + } +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath)); +- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath)); ++ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend, ++ &nicinfo->backend_id); ++ if (rc) goto out; ++ ++ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath)); + nicinfo->state = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath)); + nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1; +@@ -3183,8 +3188,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, + val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend)); + nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; + ++ rc = 0; ++ out: + GC_FREE; +- return 0; ++ return rc; + } + + const char *libxl__device_nic_devname(libxl__gc *gc, +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0011-libxl-Cleanup-Have-libxl__alloc_vdev-use-libxl.patch xen-4.4.2/debian/patches/xsa175-4.4-0011-libxl-Cleanup-Have-libxl__alloc_vdev-use-libxl.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0011-libxl-Cleanup-Have-libxl__alloc_vdev-use-libxl.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0011-libxl-Cleanup-Have-libxl__alloc_vdev-use-libxl.patch 2016-06-07 13:02:49.000000000 +0000 @@ -0,0 +1,49 @@ +From 45c12108db3643cfaafad41fbeca91fdc0d73c83 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 15:25:19 +0100 +Subject: [PATCH 14/16] libxl: Cleanup: Have libxl__alloc_vdev use /libxl + +When allocating a vdev for a new disk, look in /libxl/device, rather +than the frontends directory in xenstore. + +This is more in line with the other parts of libxl, which ought not to +trust frontends. In this case, though, there is no security bug prior +to this patch because the frontend is the toolstack domain itself. + +If libxl__alloc_vdev were ever changed to take a frontend domain +argument, this patch will fix a latent security bug. + +This is a followup to XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 3a7ced6..88c85d6 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2627,7 +2627,7 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user, + { + const char *blkdev_start = (const char *) get_vdev_user; + int devid = 0, disk = 0, part = 0; +- char *dompath = libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID); ++ char *libxl_dom_path = libxl__xs_libxl_path(gc, LIBXL_TOOLSTACK_DOMID); + + libxl__device_disk_dev_number(blkdev_start, &disk, &part); + if (part != 0) { +@@ -2642,7 +2642,7 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user, + return NULL; + if (libxl__xs_read(gc, t, + libxl__sprintf(gc, "%s/device/vbd/%d/backend", +- dompath, devid)) == NULL) { ++ libxl_dom_path, devid)) == NULL) { + if (errno == ENOENT) + return libxl__devid_to_localdev(gc, devid); + else +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa175-4.4-0012-libxl-Document-serial-correctly.patch xen-4.4.2/debian/patches/xsa175-4.4-0012-libxl-Document-serial-correctly.patch --- xen-4.4.2/debian/patches/xsa175-4.4-0012-libxl-Document-serial-correctly.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa175-4.4-0012-libxl-Document-serial-correctly.patch 2016-06-07 13:03:14.000000000 +0000 @@ -0,0 +1,39 @@ +From aea2669313d95739253745078e37d97a2f5d1fb9 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 15:17:45 +0100 +Subject: [PATCH 16/16] libxl: Document ~/serial/ correctly + +xenstore-paths.markdown talked about ~/device/serial/, but that's not +used. + +(It is very wrong for this value, which contains a driver domain +filesystem path, to be in the guest's area of xenstore. However, it +is only ever created by libxl and ready by xenconsoled. When it is +created, it inherits the read-only permissions of /local/domain/DOMID. +So there is no security bug.) + +This is a followup to XSA-175. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + docs/misc/xenstore-paths.markdown | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown +index c2e2842..70d6fad 100644 +--- a/docs/misc/xenstore-paths.markdown ++++ b/docs/misc/xenstore-paths.markdown +@@ -232,7 +232,7 @@ The primary PV console device. Described in [console.txt](console.txt) + + A secondary PV console device. Described in [console.txt](console.txt) + +-#### ~/device/serial/$DEVID/* [HVM] ++#### ~/serial/$DEVID/* [HVM] + + An emulated serial device. Described in [console.txt](console.txt) + +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa176.patch xen-4.4.2/debian/patches/xsa176.patch --- xen-4.4.2/debian/patches/xsa176.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa176.patch 2016-06-06 12:18:45.000000000 +0000 @@ -0,0 +1,45 @@ +x86/mm: fully honor PS bits in guest page table walks + +In L4 entries it is currently unconditionally reserved (and hence +should, when set, always result in a reserved bit page fault), and is +reserved on hardware not supporting 1Gb pages (and hence should, when +set, similarly cause a reserved bit page fault on such hardware). + +This is CVE-2016-4480 / XSA-176. + +Signed-off-by: Jan Beulich +Reviewed-by: Andrew Cooper +Tested-by: Andrew Cooper + +--- a/xen/arch/x86/mm/guest_walk.c ++++ b/xen/arch/x86/mm/guest_walk.c +@@ -226,6 +226,11 @@ guest_walk_tables(struct vcpu *v, struct + rc |= _PAGE_PRESENT; + goto out; + } ++ if ( gflags & _PAGE_PSE ) ++ { ++ rc |= _PAGE_PSE | _PAGE_INVALID_BIT; ++ goto out; ++ } + rc |= ((gflags & mflags) ^ mflags); + + /* Map the l3 table */ +@@ -247,7 +252,7 @@ guest_walk_tables(struct vcpu *v, struct + } + rc |= ((gflags & mflags) ^ mflags); + +- pse1G = (gflags & _PAGE_PSE) && guest_supports_1G_superpages(v); ++ pse1G = !!(gflags & _PAGE_PSE); + + if ( pse1G ) + { +@@ -267,6 +272,8 @@ guest_walk_tables(struct vcpu *v, struct + /* _PAGE_PSE_PAT not set: remove _PAGE_PAT from flags. */ + flags &= ~_PAGE_PAT; + ++ if ( !guest_supports_1G_superpages(v) ) ++ rc |= _PAGE_PSE | _PAGE_INVALID_BIT; + if ( gfn_x(start) & GUEST_L3_GFN_MASK & ~0x1 ) + rc |= _PAGE_INVALID_BITS; + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0001-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-excep.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0001-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-excep.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0001-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-excep.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0001-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-excep.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,56 @@ +From 7bd50f1bd68b1b754f67e076498a77421edb0701 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 17:18:44 +0100 +Subject: [PATCH 01/16] libxl: Do not trust backend for vtpm in getinfo (except + uuid) + +* Do not check the backend for existence. We have already read the + /libxl path so know that the vtpm exists (or is supposed to); if the + backend doesn't exist then that must be the backend's doing. +* Get the frontend path from the /libxl directory. +* The frontend domid is the guest domid, and does not need to be read + from xenstore (!) + +We still attempt to read the uuid from the backend. This will be +fixed in the next patch. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index c794d3a..b4ed33f 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1944,9 +1944,6 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + if (!vtpminfo->backend) { + goto err; + } +- if(!libxl__xs_read(gc, XBT_NULL, vtpminfo->backend)) { +- goto err; +- } + + rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend, + &vtpminfo->backend_id); +@@ -1965,11 +1962,8 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + vtpminfo->rref = val ? strtoul(val, NULL, 10) : -1; + + vtpminfo->frontend = xs_read(ctx->xsh, XBT_NULL, +- GCSPRINTF("%s/frontend", vtpminfo->backend), NULL); +- +- val = libxl__xs_read(gc, XBT_NULL, +- GCSPRINTF("%s/frontend-id", vtpminfo->backend)); +- vtpminfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; ++ GCSPRINTF("%s/frontend", libxl_path), NULL); ++ vtpminfo->frontend_id = domid; + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/uuid", vtpminfo->backend)); +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0002-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-uuid.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0002-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-uuid.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0002-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-uuid.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0002-libxl-Do-not-trust-backend-for-vtpm-in-getinfo-uuid.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,47 @@ +From 17d70465f9ad590b8443322d2045ea9dfaed2a7f Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 16:57:14 +0100 +Subject: [PATCH 02/16] libxl: Do not trust backend for vtpm in getinfo (uuid) + +Use uuid from /libxl, rather than from backend. I think the backend +is not supposed to change the uuid, since it seems to be set by libxl +during setup. + +If in fact the backend is supposed to be able to change the uuid, this +patch needs to be dropped and replaced by a patch which makes the vtpm +uuid lookup tolerate bad or missing data. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index b4ed33f..19c3d90 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1906,7 +1906,7 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n + &vtpm->backend_domid); + if (rc) return NULL; + +- tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path)); ++ tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", libxl_path)); + if (tmp) { + if(libxl_uuid_from_string(&(vtpm->uuid), tmp)) { + LOG(ERROR, "%s/uuid is a malformed uuid?? (%s) Probably a bug!!\n", be_path, tmp); +@@ -1966,7 +1966,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx, + vtpminfo->frontend_id = domid; + + val = libxl__xs_read(gc, XBT_NULL, +- GCSPRINTF("%s/uuid", vtpminfo->backend)); ++ GCSPRINTF("%s/uuid", libxl_path)); + if(val == NULL) { + LOG(ERROR, "%s/uuid does not exist!\n", vtpminfo->backend); + goto err; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0003-libxl-cdrom-eject-and-insert-write-to-libxl.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0003-libxl-cdrom-eject-and-insert-write-to-libxl.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0003-libxl-cdrom-eject-and-insert-write-to-libxl.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0003-libxl-cdrom-eject-and-insert-write-to-libxl.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,80 @@ +From 64282177f44fccf8fa9d8df7e1ab72d59a0fb0c8 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 19:15:13 +0100 +Subject: [PATCH 03/16] libxl: cdrom eject and insert: write to /libxl + +Copy the new type and params values to /libxl, so that the information +in /libxl is kept up to date. + +This is needed so that we can return this trustworthy information, +rather than trusting the backend-writeable parts of xenstore. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 19c3d90..2f043a7 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2496,7 +2496,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + int rc, dm_ver; + + libxl__device device; +- const char * path; ++ const char *path, *libxl_path; ++ xs_transaction_t t = XBT_NULL; + char * tmp; + + flexarray_t *insert = NULL; +@@ -2557,6 +2558,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + } + + path = libxl__device_backend_path(gc, &device); ++ libxl_path = libxl__device_libxl_path(gc, &device); + + /* Sanity check: make sure the backend exists before writing here */ + tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend", path)); +@@ -2581,9 +2583,22 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + else + flexarray_append_pair(insert, "params", ""); + +- rc = libxl__xs_writev_atonce(gc, path, +- libxl__xs_kvs_of_flexarray(gc, insert, insert->count)); +- if (rc) goto out; ++ char **kvs = libxl__xs_kvs_of_flexarray(gc, insert, insert->count); ++ ++ for (;;) { ++ rc = libxl__xs_transaction_start(gc, &t); ++ if (rc) goto out; ++ ++ rc = libxl__xs_writev(gc, t, path, kvs); ++ if (rc) goto out; ++ ++ rc = libxl__xs_writev(gc, t, libxl_path, kvs); ++ if (rc) goto out; ++ ++ rc = libxl__xs_transaction_commit(gc, &t); ++ if (!rc) break; ++ if (rc<0) goto out; ++ } + + /* success, no actual async */ + libxl__ao_complete(egc, ao, 0); +@@ -2595,6 +2610,8 @@ out: + libxl_device_disk_dispose(&disks[i]); + free(disks); + ++ libxl__xs_transaction_abort(gc, &t); ++ + if (rc) return AO_ABORT(rc); + return AO_INPROGRESS; + } +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0004-libxl-Do-not-trust-backend-for-disk-eject-vdev.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0004-libxl-Do-not-trust-backend-for-disk-eject-vdev.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0004-libxl-Do-not-trust-backend-for-disk-eject-vdev.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0004-libxl-Do-not-trust-backend-for-disk-eject-vdev.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,68 @@ +From 35343222aef036cf65ab850ba9ba73cd36a916d7 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 16:23:35 +0100 +Subject: [PATCH 04/16] libxl: Do not trust backend for disk eject vdev + +For disk eject, use configured vdev from /libxl, not backend. + +The backend directory is writeable by driver domains. This means that +a malicious driver domain could cause libxl to see a wrong vdev, +confusing the user or the toolstack. + +Use the vdev from the /libxl space, rather than the backend. + +For convenience, we read the vdev from the /libxl space into the evg +during setup and copy it on each event, rather than reading it afresh +each time (which would in any case involve generating or saving a copy +of the relevant /libxl path). + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 2f043a7..df62bcc 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1186,8 +1186,7 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w, + disk->pdev_path = strdup(""); /* xxx fixme malloc failure */ + disk->format = LIBXL_DISK_FORMAT_EMPTY; + /* this value is returned to the user: do not free right away */ +- disk->vdev = xs_read(CTX->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/dev", backend), NULL); ++ disk->vdev = libxl__strdup(NOGC, evg->vdev); + disk->removable = 1; + disk->readwrite = 0; + disk->is_cdrom = 1; +@@ -1210,9 +1209,6 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid, + evg->domid = guest_domid; + LIBXL_LIST_INSERT_HEAD(&CTX->disk_eject_evgens, evg, entry); + +- evg->vdev = strdup(vdev); +- if (!evg->vdev) { rc = ERROR_NOMEM; goto out; } +- + uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid); + + if (!domid) +@@ -1230,6 +1226,13 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid, + devid); + evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path); + ++ const char *configured_vdev; ++ rc = libxl__xs_read_checked(gc, XBT_NULL, ++ GCSPRINTF("%s/vdev", libxl_path), &configured_vdev); ++ if (rc) goto out; ++ ++ evg->vdev = libxl__strdup(NOGC, configured_vdev); ++ + rc = libxl__ev_xswatch_register(gc, &evg->watch, + disk_eject_xswatch_callback, path); + if (rc) goto out; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0005-libxl-Do-not-trust-backend-for-disk-fix-driver-domai.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0005-libxl-Do-not-trust-backend-for-disk-fix-driver-domai.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0005-libxl-Do-not-trust-backend-for-disk-fix-driver-domai.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0005-libxl-Do-not-trust-backend-for-disk-fix-driver-domai.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,247 @@ +From 5f0749272567c4f7403b9d3f45ab94f91da84a20 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 18:29:45 +0100 +Subject: [PATCH 05/16] libxl: Do not trust backend for disk; fix driver domain + disks list + +Rework libxl__device_disk_from_xs_be (which takes a backend path) into +to libxl__device_disk_from_xenstore (which takes a libxl path). + +libxl__device_disk_from_xenstore now finds the backend path itself, +although it doesn't use it any more for most of its functions. We +rename the variable from be_path to backend_path to make sure we +didn't miss any cases. + +All the data collection is now done by reading from the copy in +/libxl. + +libxl_device_disk_list and its helper libxl__append_disk_list (which +used to be libxl__append_disk_list_of_type) need extensive rework, +because they now need to specify the /libxl path rather than the +backend path. + +To do that they enumerate disks by looking in the appropriate area in +/libxl. Previously they scanned various of the backend directories in +dom0 (which was broken for driver domains). It is no longer necessary +to enumerate the various disk backends, because they all use the same +paths in /devices. libxl__device_disk_from_xenstore will parse the +type out of the backend path, for itself. (Indeed, it did so before - +the now-gone type parameter to libxl__append_disk_list_of_type wasn't +used other than to construct the directory to list.) + +Finally, remove a redundant store to pdisk->backend_domid in +libxl__append_disk_list[_of_type]. Even before this commit, that +store was not needed because libxl_device_disk_init (called by +libxl__device_disk_from_xenstore) would zero it. Now it overwrites +the correct backend domid with zero; so remove it. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +--- +v2: Also fix up COLO reads, following rebase + +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 84 +++++++++++++++++++++++++++-------------------------- + 1 file changed, 43 insertions(+), 41 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index df62bcc..cab98e0 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2270,8 +2270,8 @@ void libxl__device_disk_add(libxl__egc *egc, uint32_t domid, + device_disk_add(egc, domid, disk, aodev, NULL, NULL); + } + +-static int libxl__device_disk_from_xs_be(libxl__gc *gc, +- const char *be_path, ++static int libxl__device_disk_from_xenstore(libxl__gc *gc, ++ const char *libxl_path, + libxl_device_disk *disk) + { + libxl_ctx *ctx = libxl__gc_owner(gc); +@@ -2281,15 +2281,27 @@ static int libxl__device_disk_from_xs_be(libxl__gc *gc, + + libxl_device_disk_init(disk); + +- rc = sscanf(be_path, "/local/domain/%d/", &disk->backend_domid); ++ const char *backend_path; ++ rc = libxl__xs_read_checked(gc, XBT_NULL, ++ GCSPRINTF("%s/backend", libxl_path), ++ &backend_path); ++ if (rc) goto out; ++ ++ if (!backend_path) { ++ LOG(ERROR, "disk %s does not exist (no backend path", libxl_path); ++ rc = ERROR_FAIL; ++ goto out; ++ } ++ ++ rc = sscanf(backend_path, "/local/domain/%d/", &disk->backend_domid); + if (rc != 1) { +- LOG(ERROR, "Unable to fetch device backend domid from %s", be_path); ++ LOG(ERROR, "Unable to fetch device backend domid from %s", backend_path); + goto cleanup; + } + + /* "params" may not be present; but everything else must be. */ + tmp = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/params", be_path), &len); ++ libxl__sprintf(gc, "%s/params", libxl_path), &len); + if (tmp && strchr(tmp, ':')) { + disk->pdev_path = strdup(strchr(tmp, ':') + 1); + free(tmp); +@@ -2299,31 +2311,31 @@ static int libxl__device_disk_from_xs_be(libxl__gc *gc, + + + tmp = libxl__xs_read(gc, XBT_NULL, +- libxl__sprintf(gc, "%s/type", be_path)); ++ libxl__sprintf(gc, "%s/type", libxl_path)); + if (!tmp) { +- LOG(ERROR, "Missing xenstore node %s/type", be_path); ++ LOG(ERROR, "Missing xenstore node %s/type", libxl_path); + goto cleanup; + } + libxl_string_to_backend(ctx, tmp, &(disk->backend)); + + disk->vdev = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/dev", be_path), &len); ++ libxl__sprintf(gc, "%s/dev", libxl_path), &len); + if (!disk->vdev) { +- LOG(ERROR, "Missing xenstore node %s/dev", be_path); ++ LOG(ERROR, "Missing xenstore node %s/dev", libxl_path); + goto cleanup; + } + + tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf +- (gc, "%s/removable", be_path)); ++ (gc, "%s/removable", libxl_path)); + if (!tmp) { +- LOG(ERROR, "Missing xenstore node %s/removable", be_path); ++ LOG(ERROR, "Missing xenstore node %s/removable", libxl_path); + goto cleanup; + } + disk->removable = atoi(tmp); + +- tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/mode", be_path)); ++ tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/mode", libxl_path)); + if (!tmp) { +- LOG(ERROR, "Missing xenstore node %s/mode", be_path); ++ LOG(ERROR, "Missing xenstore node %s/mode", libxl_path); + goto cleanup; + } + if (!strcmp(tmp, "w")) +@@ -2332,9 +2344,9 @@ static int libxl__device_disk_from_xs_be(libxl__gc *gc, + disk->readwrite = 0; + + tmp = libxl__xs_read(gc, XBT_NULL, +- libxl__sprintf(gc, "%s/device-type", be_path)); ++ libxl__sprintf(gc, "%s/device-type", libxl_path)); + if (!tmp) { +- LOG(ERROR, "Missing xenstore node %s/device-type", be_path); ++ LOG(ERROR, "Missing xenstore node %s/device-type", libxl_path); + goto cleanup; + } + disk->is_cdrom = !strcmp(tmp, "cdrom"); +@@ -2343,15 +2355,17 @@ static int libxl__device_disk_from_xs_be(libxl__gc *gc, + + return 0; + cleanup: ++ rc = ERROR_FAIL; ++ out: + libxl_device_disk_dispose(disk); +- return ERROR_FAIL; ++ return rc; + } + + int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, + const char *vdev, libxl_device_disk *disk) + { + GC_INIT(ctx); +- char *dompath, *path; ++ char *dom_xl_path, *libxl_path; + int devid = libxl__device_disk_dev_number(vdev, NULL, NULL); + int rc = ERROR_FAIL; + +@@ -2360,39 +2374,34 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, + + libxl_device_disk_init(disk); + +- dompath = libxl__xs_get_dompath(gc, domid); +- if (!dompath) { ++ dom_xl_path = libxl__xs_libxl_path(gc, domid); ++ if (!dom_xl_path) { + goto out; + } +- path = libxl__xs_read(gc, XBT_NULL, +- libxl__sprintf(gc, "%s/device/vbd/%d/backend", +- dompath, devid)); +- if (!path) +- goto out; ++ libxl_path = GCSPRINTF("%s/device/vbd/%d", dom_xl_path, devid); + +- rc = libxl__device_disk_from_xs_be(gc, path, disk); ++ rc = libxl__device_disk_from_xenstore(gc, libxl_path, disk); + out: + GC_FREE; + return rc; + } + + +-static int libxl__append_disk_list_of_type(libxl__gc *gc, ++static int libxl__append_disk_list(libxl__gc *gc, + uint32_t domid, +- const char *type, + libxl_device_disk **disks, + int *ndisks) + { +- char *be_path = NULL; ++ char *libxl_dir_path = NULL; + char **dir = NULL; + unsigned int n = 0; + libxl_device_disk *pdisk = NULL, *pdisk_end = NULL; + int rc=0; + int initial_disks = *ndisks; + +- be_path = libxl__sprintf(gc, "%s/backend/%s/%d", +- libxl__xs_get_dompath(gc, 0), type, domid); +- dir = libxl__xs_directory(gc, XBT_NULL, be_path, &n); ++ libxl_dir_path = GCSPRINTF("%s/device/vbd", ++ libxl__xs_libxl_path(gc, domid)); ++ dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n); + if (dir && n) { + libxl_device_disk *tmp; + tmp = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n)); +@@ -2403,10 +2412,9 @@ static int libxl__append_disk_list_of_type(libxl__gc *gc, + pdisk_end = *disks + initial_disks + n; + for (; pdisk < pdisk_end; pdisk++, dir++) { + const char *p; +- p = libxl__sprintf(gc, "%s/%s", be_path, *dir); +- if ((rc=libxl__device_disk_from_xs_be(gc, p, pdisk))) ++ p = libxl__sprintf(gc, "%s/%s", libxl_dir_path, *dir); ++ if ((rc=libxl__device_disk_from_xenstore(gc, p, pdisk))) + goto out; +- pdisk->backend_domid = 0; + *ndisks += 1; + } + } +@@ -2422,13 +2430,7 @@ libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *n + + *num = 0; + +- rc = libxl__append_disk_list_of_type(gc, domid, "vbd", &disks, num); +- if (rc) goto out_err; +- +- rc = libxl__append_disk_list_of_type(gc, domid, "tap", &disks, num); +- if (rc) goto out_err; +- +- rc = libxl__append_disk_list_of_type(gc, domid, "qdisk", &disks, num); ++ rc = libxl__append_disk_list(gc, domid, &disks, num); + if (rc) goto out_err; + + GC_FREE; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0006-libxl-Do-not-trust-backend-for-disk-in-getinfo.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0006-libxl-Do-not-trust-backend-for-disk-in-getinfo.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0006-libxl-Do-not-trust-backend-for-disk-in-getinfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0006-libxl-Do-not-trust-backend-for-disk-in-getinfo.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,36 @@ +From 2dbe3631693ac13c74d31c6e30c12447d4c62854 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 19:10:45 +0100 +Subject: [PATCH 06/16] libxl: Do not trust backend for disk in getinfo + +Do not read the frontend path out of the backend. We have it in our +hand. Likewise the guest (frontend) domid was one of our parameters (!) + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index cab98e0..01d41b1 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2480,9 +2480,8 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path)); + diskinfo->rref = val ? strtoul(val, NULL, 10) : -1; + diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL); +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", diskinfo->backend)); +- diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; ++ GCSPRINTF("%s/frontend", libxl_path), NULL); ++ diskinfo->frontend_id = domid; + + GC_FREE; + return 0; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0007-libxl-Do-not-trust-backend-for-cdrom-insert.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0007-libxl-Do-not-trust-backend-for-cdrom-insert.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0007-libxl-Do-not-trust-backend-for-cdrom-insert.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0007-libxl-Do-not-trust-backend-for-cdrom-insert.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,66 @@ +From 98d7429a69e58b0cd58451b631ecfa4943feb590 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 19:13:17 +0100 +Subject: [PATCH 07/16] libxl: Do not trust backend for cdrom insert + +Use the /libxl path where appropriate. Rename `path' variable to +`be_path' to make sure we caught all the occurrences. + +Specifically, when checking that the device still exists, check the +`frontend' value in /libxl, rather than anything in the backend +directory. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 01d41b1..362fb22 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2500,7 +2500,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + int rc, dm_ver; + + libxl__device device; +- const char *path, *libxl_path; ++ const char *be_path, *libxl_path; + xs_transaction_t t = XBT_NULL; + char * tmp; + +@@ -2561,15 +2561,15 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + if (rc) goto out; + } + +- path = libxl__device_backend_path(gc, &device); ++ be_path = libxl__device_backend_path(gc, &device); + libxl_path = libxl__device_libxl_path(gc, &device); + +- /* Sanity check: make sure the backend exists before writing here */ +- tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend", path)); ++ /* Sanity check: make sure the device exists before writing here */ ++ tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend", libxl_path)); + if (!tmp) + { + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Internal error: %s does not exist", +- libxl__sprintf(gc, "%s/frontend", path)); ++ libxl__sprintf(gc, "%s/frontend", libxl_path)); + rc = ERROR_FAIL; + goto out; + } +@@ -2593,7 +2593,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, + rc = libxl__xs_transaction_start(gc, &t); + if (rc) goto out; + +- rc = libxl__xs_writev(gc, t, path, kvs); ++ rc = libxl__xs_writev(gc, t, be_path, kvs); + if (rc) goto out; + + rc = libxl__xs_writev(gc, t, libxl_path, kvs); +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0008-libxl-Rename-libxl__device_nic_from_xs_be-to-_from_x.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0008-libxl-Rename-libxl__device_nic_from_xs_be-to-_from_x.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0008-libxl-Rename-libxl__device_nic_from_xs_be-to-_from_x.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0008-libxl-Rename-libxl__device_nic_from_xs_be-to-_from_x.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,61 @@ +From 0eb5ef298605a6cbf3de1bf15eb1b9bc856066a9 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 16:18:36 +0100 +Subject: [PATCH 08/16] libxl: Rename libxl__device_nic_from_xs_be to + _from_xenstore + +We are going to change these functions to expect, and be passed, a +/libxl path. So it is wrong that they are called _from_xs_be. + +Neither function reads anything which isn't found in both places, so +we can and will change the call sites later. + +The only remaining function in libxl called *_from_xs_be relates to +PCI devices, for which the backend domain is hardcoded to 0 throughout +the libxl_pci.c. + +No functional change. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 362fb22..5a9a05e 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3030,7 +3030,7 @@ out: + return; + } + +-static int libxl__device_nic_from_xs_be(libxl__gc *gc, ++static int libxl__device_nic_from_xenstore(libxl__gc *gc, + const char *be_path, + libxl_device_nic *nic) + { +@@ -3095,7 +3095,7 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, + if (!path) + goto out; + +- rc = libxl__device_nic_from_xs_be(gc, path, nic); ++ rc = libxl__device_nic_from_xenstore(gc, path, nic); + if (rc) goto out; + + rc = 0; +@@ -3130,7 +3130,7 @@ static int libxl__append_nic_list_of_type(libxl__gc *gc, + for (; pnic < pnic_end; pnic++, dir++) { + const char *p; + p = libxl__sprintf(gc, "%s/%s", be_path, *dir); +- rc = libxl__device_nic_from_xs_be(gc, p, pnic); ++ rc = libxl__device_nic_from_xenstore(gc, p, pnic); + if (rc) goto out; + pnic->backend_domid = 0; + } +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0009-libxl-Rename-READ_BACKEND-to-READ_LIBXLDEV.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0009-libxl-Rename-READ_BACKEND-to-READ_LIBXLDEV.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0009-libxl-Rename-READ_BACKEND-to-READ_LIBXLDEV.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0009-libxl-Rename-READ_BACKEND-to-READ_LIBXLDEV.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,79 @@ +From c1f9a268b8ad4b1052843e10960b0d2bf3f702e2 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 16:07:02 +0100 +Subject: [PATCH 09/16] libxl: Rename READ_BACKEND to READ_LIBXLDEV + +We are going to want to change all the functions that use READ_BACKEND +to get untrustworthy information from the backend, to use trustworthy +information from /libxl. + +This will involve replacing READ_BACKEND, which reads from be_path, +with a similar macro READ_LIBXLDEV, which reads from libxl_path. + +The macro name change generates a lot of clutter in the diff. So we +break it out into this separate patch. Here, we rename the macro, but +the implementation does not really match the new name. + +So, another way to look at this, is that we have transformed the bug: + * All of the backends use READ_BACKEND, which is unsafe +into the new bug: + * READ_LIBXLDEV actually reads be_path, which is unsafe. + +There is no functional change as yet. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 5a9a05e..ed7687b 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3039,7 +3039,7 @@ static int libxl__device_nic_from_xenstore(libxl__gc *gc, + + libxl_device_nic_init(nic); + +-#define READ_BACKEND(tgc, subpath) ({ \ ++#define READ_LIBXLDEV(tgc, subpath) ({ \ + rc = libxl__xs_read_checked(tgc, XBT_NULL, \ + GCSPRINTF("%s/" subpath, be_path), \ + &tmp); \ +@@ -3047,7 +3047,7 @@ static int libxl__device_nic_from_xenstore(libxl__gc *gc, + (char*)tmp; \ + }); + +- tmp = READ_BACKEND(gc, "handle"); ++ tmp = READ_LIBXLDEV(gc, "handle"); + if (tmp) + nic->devid = atoi(tmp); + else +@@ -3055,7 +3055,7 @@ static int libxl__device_nic_from_xenstore(libxl__gc *gc, + + /* nic->mtu = */ + +- tmp = READ_BACKEND(gc, "mac"); ++ tmp = READ_LIBXLDEV(gc, "mac"); + if (tmp) { + rc = libxl__parse_mac(tmp, nic->mac); + if (rc) goto out; +@@ -3063,9 +3063,9 @@ static int libxl__device_nic_from_xenstore(libxl__gc *gc, + memset(nic->mac, 0, sizeof(nic->mac)); + } + +- nic->ip = READ_BACKEND(NOGC, "ip"); +- nic->bridge = READ_BACKEND(NOGC, "bridge"); +- nic->script = READ_BACKEND(NOGC, "script"); ++ nic->ip = READ_LIBXLDEV(NOGC, "ip"); ++ nic->bridge = READ_LIBXLDEV(NOGC, "bridge"); ++ nic->script = READ_LIBXLDEV(NOGC, "script"); + + /* vif_ioemu nics use the same xenstore entries as vif interfaces */ + nic->nictype = LIBXL_NIC_TYPE_VIF; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0010-libxl-Have-READ_LIBXLDEV-use-libxl_path-rather-than-.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0010-libxl-Have-READ_LIBXLDEV-use-libxl_path-rather-than-.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0010-libxl-Have-READ_LIBXLDEV-use-libxl_path-rather-than-.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0010-libxl-Have-READ_LIBXLDEV-use-libxl_path-rather-than-.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,50 @@ +From 7e42cb64bcf6cdfe679c04fede8fb6f45cf75a84 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 15:40:18 +0100 +Subject: [PATCH 10/16] libxl: Have READ_LIBXLDEV use libxl_path rather than + be_path + +Fix the just-introduced bug in this macro: now it reads the +trustworthy libxl_path. Change the variable name in the two functions +(nic and channel) which use it. + +Shuffling the bump in the carpet along, we now introduce three new +bugs: the three call sites pass a backend path where a frontend path +is expected. + +No functional change. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index ed7687b..0bf1c5b 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3031,7 +3031,7 @@ out: + } + + static int libxl__device_nic_from_xenstore(libxl__gc *gc, +- const char *be_path, ++ const char *libxl_path, + libxl_device_nic *nic) + { + const char *tmp; +@@ -3041,7 +3041,7 @@ static int libxl__device_nic_from_xenstore(libxl__gc *gc, + + #define READ_LIBXLDEV(tgc, subpath) ({ \ + rc = libxl__xs_read_checked(tgc, XBT_NULL, \ +- GCSPRINTF("%s/" subpath, be_path), \ ++ GCSPRINTF("%s/" subpath, libxl_path), \ + &tmp); \ + if (rc) goto out; \ + (char*)tmp; \ +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0011-libxl-Do-not-trust-backend-in-nic-getinfo.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0011-libxl-Do-not-trust-backend-in-nic-getinfo.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0011-libxl-Do-not-trust-backend-in-nic-getinfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0011-libxl-Do-not-trust-backend-in-nic-getinfo.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,34 @@ +From 35fe0d66632fa6e7e6e250c8be90ba558e081037 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Tue, 3 May 2016 16:35:21 +0100 +Subject: [PATCH 11/16] libxl: Do not trust backend in nic getinfo + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 0bf1c5b..d20924c 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3198,10 +3198,8 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, + nicinfo->rref_tx = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/rx-ring-ref", nicpath)); + nicinfo->rref_rx = val ? strtoul(val, NULL, 10) : -1; +- nicinfo->frontend = xs_read(ctx->xsh, XBT_NULL, +- libxl__sprintf(gc, "%s/frontend", nicinfo->backend), NULL); +- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend)); +- nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; ++ nicinfo->frontend = libxl__strdup(NOGC, nicpath); ++ nicinfo->frontend_id = domid; + + rc = 0; + out: +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0012-libxl-Do-not-trust-backend-for-nic-in-devid_to_devic.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0012-libxl-Do-not-trust-backend-for-nic-in-devid_to_devic.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0012-libxl-Do-not-trust-backend-for-nic-in-devid_to_devic.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0012-libxl-Do-not-trust-backend-for-nic-in-devid_to_devic.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,49 @@ +From 9b2061daa55fe42470435cdfd0529203a0ad1e40 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 16:20:05 +0100 +Subject: [PATCH 12/16] libxl: Do not trust backend for nic in devid_to_device + +libxl_devid_to_device_nic should read the information it needs from +the /libxl/device path, not the backend. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index d20924c..ec141b5 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3081,7 +3081,7 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_nic *nic) + { + GC_INIT(ctx); +- char *libxl_dom_path, *path; ++ char *libxl_dom_path, *libxl_path; + int rc = ERROR_FAIL; + + libxl_device_nic_init(nic); +@@ -3089,13 +3089,9 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, + if (!libxl_dom_path) + goto out; + +- path = libxl__xs_read(gc, XBT_NULL, +- GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path, +- devid)); +- if (!path) +- goto out; ++ libxl_path = GCSPRINTF("%s/device/vif/%d", libxl_dom_path, devid); + +- rc = libxl__device_nic_from_xenstore(gc, path, nic); ++ rc = libxl__device_nic_from_xenstore(gc, libxl_path, nic); + if (rc) goto out; + + rc = 0; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0013-libxl-Do-not-trust-backend-for-nic-in-list.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0013-libxl-Do-not-trust-backend-for-nic-in-list.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0013-libxl-Do-not-trust-backend-for-nic-in-list.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0013-libxl-Do-not-trust-backend-for-nic-in-list.patch 2016-06-07 12:54:29.000000000 +0000 @@ -0,0 +1,81 @@ +From a0b99aba04d95f4345b3d141d802c5baf8177bb1 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 4 May 2016 16:23:57 +0100 +Subject: [PATCH 13/16] libxl: Do not trust backend for nic in list + +libxl_device_nic_list should use the /libxl path to search for +devices, and for obtaining the device information. + +The "type" parameter was always "vif". Abolish it. (In any case, +paths in /libxl/device are named after the frontend type which is +constant, not the backend type which might in future vary.) + +Abolish a redundant store to pnic->backend_domid. Before this commit, +that store was not needed because libxl_device_nic_init (called by +libxl__device_nic_from_xenstore) would zero it. Now it overwrites the +correct backend domid with zero; so remove it. + +This is part of XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index ec141b5..3a7ced6 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -3100,21 +3100,20 @@ out: + return rc; + } + +-static int libxl__append_nic_list_of_type(libxl__gc *gc, ++static int libxl__append_nic_list(libxl__gc *gc, + uint32_t domid, +- const char *type, + libxl_device_nic **nics, + int *nnics) + { +- char *be_path = NULL; ++ char *libxl_dir_path = NULL; + char **dir = NULL; + unsigned int n = 0; + libxl_device_nic *pnic = NULL, *pnic_end = NULL; + int rc; + +- be_path = libxl__sprintf(gc, "%s/backend/%s/%d", +- libxl__xs_get_dompath(gc, 0), type, domid); +- dir = libxl__xs_directory(gc, XBT_NULL, be_path, &n); ++ libxl_dir_path = GCSPRINTF("%s/device/vif", ++ libxl__xs_libxl_path(gc, domid)); ++ dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n); + if (dir && n) { + libxl_device_nic *tmp; + tmp = realloc(*nics, sizeof (libxl_device_nic) * (*nnics + n)); +@@ -3125,10 +3124,9 @@ static int libxl__append_nic_list_of_type(libxl__gc *gc, + pnic_end = *nics + *nnics + n; + for (; pnic < pnic_end; pnic++, dir++) { + const char *p; +- p = libxl__sprintf(gc, "%s/%s", be_path, *dir); ++ p = GCSPRINTF("%s/%s", libxl_dir_path, *dir); + rc = libxl__device_nic_from_xenstore(gc, p, pnic); + if (rc) goto out; +- pnic->backend_domid = 0; + } + *nnics += n; + } +@@ -3146,7 +3144,7 @@ libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num + + *num = 0; + +- rc = libxl__append_nic_list_of_type(gc, domid, "vif", &nics, num); ++ rc = libxl__append_nic_list(gc, domid, &nics, num); + if (rc) goto out_err; + + GC_FREE; +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0014-libxl-Cleanup-use-libxl__backendpath_parse_domid-in-.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0014-libxl-Cleanup-use-libxl__backendpath_parse_domid-in-.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0014-libxl-Cleanup-use-libxl__backendpath_parse_domid-in-.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0014-libxl-Cleanup-use-libxl__backendpath_parse_domid-in-.patch 2016-06-07 13:08:55.000000000 +0000 @@ -0,0 +1,39 @@ +From 8ce712fc84bc9054424a60bc7600dd3163f0fc1d Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Fri, 29 Apr 2016 16:08:19 +0100 +Subject: [PATCH 15/16] libxl: Cleanup: use libxl__backendpath_parse_domid in + libxl__device_disk_from_xs_be + +Rather than an open-coded sscanf. No functional change with correct +input. + +This is a followup to XSA-175 and XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 88c85d6..30b6878 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -2293,10 +2293,10 @@ static int libxl__device_disk_from_xenstore(libxl__gc *gc, + goto out; + } + +- rc = sscanf(backend_path, "/local/domain/%d/", &disk->backend_domid); +- if (rc != 1) { ++ rc = libxl__backendpath_parse_domid(gc, backend_path, &disk->backend_domid); ++ if (rc) { + LOG(ERROR, "Unable to fetch device backend domid from %s", backend_path); +- goto cleanup; ++ goto out; + } + + /* "params" may not be present; but everything else must be. */ +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa178-xen4.4-0015-libxl-Fix-NULL-pointer-due-to-XSA-178-fix-wrong-XS-n.patch xen-4.4.2/debian/patches/xsa178-xen4.4-0015-libxl-Fix-NULL-pointer-due-to-XSA-178-fix-wrong-XS-n.patch --- xen-4.4.2/debian/patches/xsa178-xen4.4-0015-libxl-Fix-NULL-pointer-due-to-XSA-178-fix-wrong-XS-n.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa178-xen4.4-0015-libxl-Fix-NULL-pointer-due-to-XSA-178-fix-wrong-XS-n.patch 2016-06-09 13:09:07.000000000 +0000 @@ -0,0 +1,63 @@ +From ec5925c72cfd7544b86fc6273937c9cc7e21e580 Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 8 Jun 2016 15:42:19 +0100 +Subject: [PATCH] libxl: Fix NULL pointer due to XSA-178 fix wrong XS nodename + +In "libxl: Do not trust backend for disk eject vdev" (c69871a2fb26 on +xen.git#staging) we changed libxl_evenable_disk_eject to read the +device vdev out of xenstore from the /libxl path, rather than the +backend path, and to read it during setup rather than on each event. + +However, the patch has a mistake: + - GCSPRINTF("%s/dev", backend), NULL); + + GCSPRINTF("%s/vdev", libxl_path), &configured_vdev); + ^ +Spot the extra "v". This causes configured_vdev always to be NULL. +configured_vdev is passed to [libxl__]strdup. + +In Xen 4.6 and later libxl__strdup is used and tolerates NULL. +evg->vdev is set to NULL. This propagates to the `vdev' field in the +generated event. This may or may not cause further trouble, depending +on the calling application. In our osstest test cases it does not +cause any trouble, so the bug goes undetected. + +In Xen 4.5 and earlier, the strdup does not tolerate NULL, and libxl +crashes immediately. This has been detected by osstest as a +regression in Xen 4.5. + +IMO this patch should be applied immediately to + xen.git#staging-4.5 (to check that it fixes the osstest regression) + xen.git#staging (to check that it does not break master + +Subject to passes, it should then be propagated to all supported +stable trees and also be mentioned in an update to XSA-178. + +Signed-off-by: Ian Jackson +Reviewed-by: Wei Liu +CC: security@xenproject.org +CC: Jan Beulich +CC: Wei Liu +(cherry picked from commit 62b4d4769ca39fd5263da20d786a7b9a80a22d9a) +(cherry picked from commit 8b7a356409023f60f80e9f4b00bba16ad56cd77b) +(cherry picked from commit 6d272988fb3bdcc2578c5ee6d8a408628d1f0c0e) +Signed-off-by: Stefan Bader +--- + tools/libxl/libxl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index 30b6878..4083393 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -1228,7 +1228,7 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid, + + const char *configured_vdev; + rc = libxl__xs_read_checked(gc, XBT_NULL, +- GCSPRINTF("%s/vdev", libxl_path), &configured_vdev); ++ GCSPRINTF("%s/dev", libxl_path), &configured_vdev); + if (rc) goto out; + + evg->vdev = libxl__strdup(NOGC, configured_vdev); +-- +1.9.1 + diff -Nru xen-4.4.2/debian/patches/xsa179-qemut-4.4-0001-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch xen-4.4.2/debian/patches/xsa179-qemut-4.4-0001-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch --- xen-4.4.2/debian/patches/xsa179-qemut-4.4-0001-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa179-qemut-4.4-0001-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch 2016-06-07 18:08:09.000000000 +0000 @@ -0,0 +1,107 @@ +From bebb4f580901fb638016d9851a28dbb83d44b3a6 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 26 Apr 2016 08:49:10 +0200 +Subject: [PATCH 1/5] vga: fix banked access bounds checking (CVE-2016-3710) + +vga allows banked access to video memory using the window at 0xa00000 +and it supports a different access modes with different address +calculations. + +The VBE bochs extentions support banked access too, using the +VBE_DISPI_INDEX_BANK register. The code tries to take the different +address calculations into account and applies different limits to +VBE_DISPI_INDEX_BANK depending on the current access mode. + +Which is probably effective in stopping misprogramming by accident. +But from a security point of view completely useless as an attacker +can easily change access modes after setting the bank register. + +Drop the bogus check, add range checks to vga_mem_{readb,writeb} +instead. + +Fixes: CVE-2016-3710 +Reported-by: Qinghao Tang +Signed-off-by: Gerd Hoffmann +[Backport to qemu-xen-tradition] +Signed-off-by: Andrew Cooper +--- + hw/vga.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +Index: xen-4.4.2/qemu/hw/vga.c +=================================================================== +--- xen-4.4.2.orig/qemu/hw/vga.c 2016-06-07 20:07:57.256549955 +0200 ++++ xen-4.4.2/qemu/hw/vga.c 2016-06-07 20:07:57.256549955 +0200 +@@ -34,6 +34,8 @@ + + #include "qemu-timer.h" + ++#include ++ + //#define DEBUG_VGA + //#define DEBUG_VGA_MEM + //#define DEBUG_VGA_REG +@@ -606,11 +608,7 @@ static void vbe_ioport_write_data(void * + } + break; + case VBE_DISPI_INDEX_BANK: +- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { +- val &= (s->vbe_bank_mask >> 2); +- } else { +- val &= s->vbe_bank_mask; +- } ++ val &= s->vbe_bank_mask; + s->vbe_regs[s->vbe_index] = val; + s->bank_offset = (val << 16); + break; +@@ -751,13 +749,21 @@ uint32_t vga_mem_readb(void *opaque, tar + + if (s->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ ++ assert(addr < s->vram_size); + ret = s->vram_ptr[addr]; + } else if (s->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + plane = (s->gr[4] & 2) | (addr & 1); +- ret = s->vram_ptr[((addr & ~1) << 1) | plane]; ++ addr = ((addr & ~1) << 1) | plane; ++ if (addr >= s->vram_size) { ++ return 0xff; ++ } ++ ret = s->vram_ptr[addr]; + } else { + /* standard VGA latched access */ ++ if (addr * sizeof(uint32_t) >= s->vram_size) { ++ return 0xff; ++ } + s->latch = ((uint32_t *)s->vram_ptr)[addr]; + + if (!(s->gr[5] & 0x08)) { +@@ -844,6 +850,7 @@ void vga_mem_writeb(void *opaque, target + plane = addr & 3; + mask = (1 << plane); + if (s->sr[2] & mask) { ++ assert(addr < s->vram_size); + s->vram_ptr[addr] = val; + #ifdef DEBUG_VGA_MEM + printf("vga: chain4: [0x%x]\n", addr); +@@ -857,6 +864,9 @@ void vga_mem_writeb(void *opaque, target + mask = (1 << plane); + if (s->sr[2] & mask) { + addr = ((addr & ~1) << 1) | plane; ++ if (addr >= s->vram_size) { ++ return; ++ } + s->vram_ptr[addr] = val; + #ifdef DEBUG_VGA_MEM + printf("vga: odd/even: [0x%x]\n", addr); +@@ -929,6 +939,9 @@ void vga_mem_writeb(void *opaque, target + mask = s->sr[2]; + s->plane_updated |= mask; /* only used to detect font change */ + write_mask = mask16[mask]; ++ if (addr * sizeof(uint32_t) >= s->vram_size) { ++ return; ++ } + ((uint32_t *)s->vram_ptr)[addr] = + (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | + (val & write_mask); diff -Nru xen-4.4.2/debian/patches/xsa179-qemut-4.4-0002-vga-add-vbe_enabled-helper.patch xen-4.4.2/debian/patches/xsa179-qemut-4.4-0002-vga-add-vbe_enabled-helper.patch --- xen-4.4.2/debian/patches/xsa179-qemut-4.4-0002-vga-add-vbe_enabled-helper.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa179-qemut-4.4-0002-vga-add-vbe_enabled-helper.patch 2016-06-07 13:47:13.000000000 +0000 @@ -0,0 +1,67 @@ +From 34db09fb9967441408a1ff0579d553222cf17441 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 26 Apr 2016 14:11:34 +0200 +Subject: [PATCH 2/5] vga: add vbe_enabled() helper + +Makes code a bit easier to read. + +Signed-off-by: Gerd Hoffmann +[Backport to qemu-xen-tradition] +Signed-off-by: Andrew Cooper +--- + hw/vga.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +Index: xen-4.4.2/qemu/hw/vga.c +=================================================================== +--- xen-4.4.2.orig/qemu/hw/vga.c 2016-06-07 15:41:47.152796179 +0200 ++++ xen-4.4.2/qemu/hw/vga.c 2016-06-07 15:47:06.404791256 +0200 +@@ -160,6 +160,11 @@ static uint32_t expand4[256]; + static uint16_t expand2[256]; + static uint8_t expand4to8[16]; + ++static inline bool vbe_enabled(VGAState *s) ++{ ++ return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED; ++} ++ + static void vga_bios_init(VGAState *s); + static void vga_screen_dump(void *opaque, const char *filename); + +@@ -613,8 +618,7 @@ static void vbe_ioport_write_data(void * + s->bank_offset = (val << 16); + break; + case VBE_DISPI_INDEX_ENABLE: +- if ((val & VBE_DISPI_ENABLED) && +- !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) { ++ if ((val & VBE_DISPI_ENABLED) && !vbe_enabled(s)) { + int h, shift_control; + + if (s->vram_gmfn != s->lfb_addr) { +@@ -1129,7 +1133,7 @@ static void vga_get_offsets(VGAState *s, + { + uint32_t start_addr, line_offset, line_compare; + #ifdef CONFIG_BOCHS_VBE +- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { ++ if (vbe_enabled(s)) { + line_offset = s->vbe_line_offset; + start_addr = s->vbe_start_addr; + line_compare = 65535; +@@ -1515,7 +1519,7 @@ static int vga_get_bpp(VGAState *s) + { + int ret; + #ifdef CONFIG_BOCHS_VBE +- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { ++ if (vbe_enabled(s)) { + ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; + } else + #endif +@@ -1530,7 +1534,7 @@ static void vga_get_resolution(VGAState + int width, height; + + #ifdef CONFIG_BOCHS_VBE +- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { ++ if (vbe_enabled(s)) { + width = s->vbe_regs[VBE_DISPI_INDEX_XRES]; + height = s->vbe_regs[VBE_DISPI_INDEX_YRES]; + } else diff -Nru xen-4.4.2/debian/patches/xsa179-qemut-4.4-0003-vga-factor-out-vga-register-setup.patch xen-4.4.2/debian/patches/xsa179-qemut-4.4-0003-vga-factor-out-vga-register-setup.patch --- xen-4.4.2/debian/patches/xsa179-qemut-4.4-0003-vga-factor-out-vga-register-setup.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa179-qemut-4.4-0003-vga-factor-out-vga-register-setup.patch 2016-06-07 13:58:14.000000000 +0000 @@ -0,0 +1,117 @@ +From df228023ce39e8b72bd5a198b8703319b8b9ca23 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 26 Apr 2016 15:24:18 +0200 +Subject: [PATCH 3/5] vga: factor out vga register setup + +When enabling vbe mode qemu will setup a bunch of vga registers to make +sure the vga emulation operates in correct mode for a linear +framebuffer. Move that code to a separate function so we can call it +from other places too. + +Signed-off-by: Gerd Hoffmann +[Backport to qemu-xen-tradition] +Signed-off-by: Andrew Cooper +--- + hw/vga.c | 70 +++++++++++++++++++++++++++++++++++++--------------------------- + 1 file changed, 41 insertions(+), 29 deletions(-) + +Index: xen-4.4.2/qemu/hw/vga.c +=================================================================== +--- xen-4.4.2.orig/qemu/hw/vga.c 2016-06-07 15:48:40.144789811 +0200 ++++ xen-4.4.2/qemu/hw/vga.c 2016-06-07 15:58:11.440781003 +0200 +@@ -528,6 +528,44 @@ static void vga_ioport_write(void *opaqu + } + + #ifdef CONFIG_BOCHS_VBE ++/* we initialize the VGA graphic mode */ ++static void vbe_update_vgaregs(VGAState *s) ++{ ++ int h, shift_control; ++ ++ if (!vbe_enabled(s)) { ++ /* vbe is turned off -- nothing to do */ ++ return; ++ } ++ ++ /* graphic mode + memory map 1 */ ++ s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; ++ s->cr[0x17] |= 3; /* no CGA modes */ ++ s->cr[0x13] = s->vbe_line_offset >> 3; ++ /* width */ ++ s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1; ++ /* height (only meaningful if < 1024) */ ++ h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1; ++ s->cr[0x12] = h; ++ s->cr[0x07] = (s->cr[0x07] & ~0x42) | ++ ((h >> 7) & 0x02) | ((h >> 3) & 0x40); ++ /* line compare to 1023 */ ++ s->cr[0x18] = 0xff; ++ s->cr[0x07] |= 0x10; ++ s->cr[0x09] |= 0x40; ++ ++ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { ++ shift_control = 0; ++ s->sr[0x01] &= ~8; /* no double line */ ++ } else { ++ shift_control = 2; ++ s->sr[4] |= 0x08; /* set chain 4 mode */ ++ s->sr[2] |= 0x0f; /* activate all planes */ ++ } ++ s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); ++ s->cr[0x09] &= ~0x9f; /* no double scan */ ++} ++ + static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) + { + VGAState *s = opaque; +@@ -619,8 +657,6 @@ static void vbe_ioport_write_data(void * + break; + case VBE_DISPI_INDEX_ENABLE: + if ((val & VBE_DISPI_ENABLED) && !vbe_enabled(s)) { +- int h, shift_control; +- + if (s->vram_gmfn != s->lfb_addr) { + set_vram_mapping(s, s->lfb_addr, s->lfb_end); + } +@@ -638,40 +674,13 @@ static void vbe_ioport_write_data(void * + s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * + ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); + s->vbe_start_addr = 0; ++ vbe_update_vgaregs(s); + + /* clear the screen (should be done in BIOS) */ + if (!(val & VBE_DISPI_NOCLEARMEM)) { + memset(s->vram_ptr, 0, + s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); + } +- +- /* we initialize the VGA graphic mode (should be done +- in BIOS) */ +- s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */ +- s->cr[0x17] |= 3; /* no CGA modes */ +- s->cr[0x13] = s->vbe_line_offset >> 3; +- /* width */ +- s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1; +- /* height (only meaningful if < 1024) */ +- h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1; +- s->cr[0x12] = h; +- s->cr[0x07] = (s->cr[0x07] & ~0x42) | +- ((h >> 7) & 0x02) | ((h >> 3) & 0x40); +- /* line compare to 1023 */ +- s->cr[0x18] = 0xff; +- s->cr[0x07] |= 0x10; +- s->cr[0x09] |= 0x40; +- +- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { +- shift_control = 0; +- s->sr[0x01] &= ~8; /* no double line */ +- } else { +- shift_control = 2; +- s->sr[4] |= 0x08; /* set chain 4 mode */ +- s->sr[2] |= 0x0f; /* activate all planes */ +- } +- s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); +- s->cr[0x09] &= ~0x9f; /* no double scan */ + } else { + /* XXX: the bios should do that */ + s->bank_offset = 0; diff -Nru xen-4.4.2/debian/patches/xsa179-qemut-4.4-0004-vga-update-vga-register-setup-on-vbe-changes.patch xen-4.4.2/debian/patches/xsa179-qemut-4.4-0004-vga-update-vga-register-setup-on-vbe-changes.patch --- xen-4.4.2/debian/patches/xsa179-qemut-4.4-0004-vga-update-vga-register-setup-on-vbe-changes.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa179-qemut-4.4-0004-vga-update-vga-register-setup-on-vbe-changes.patch 2016-06-07 13:59:53.000000000 +0000 @@ -0,0 +1,27 @@ +From 5e840e6292825fcae90f6750a8f57bc989e28c5f Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 26 Apr 2016 15:39:22 +0200 +Subject: [PATCH 4/5] vga: update vga register setup on vbe changes + +Call the new vbe_update_vgaregs() function on vbe configuration +changes, to make sure vga registers are up-to-date. + +Signed-off-by: Gerd Hoffmann +[Backport to qemu-xen-tradition] +Signed-off-by: Andrew Cooper +--- + hw/vga.c | 1 + + 1 file changed, 1 insertion(+) + +Index: xen-4.4.2/qemu/hw/vga.c +=================================================================== +--- xen-4.4.2.orig/qemu/hw/vga.c 2016-06-07 15:58:24.560780801 +0200 ++++ xen-4.4.2/qemu/hw/vga.c 2016-06-07 15:59:48.748779503 +0200 +@@ -640,6 +640,7 @@ static void vbe_ioport_write_data(void * + case VBE_DISPI_INDEX_YRES: + if (val <= VBE_DISPI_MAX_YRES) { + s->vbe_regs[s->vbe_index] = val; ++ vbe_update_vgaregs(s); + } + break; + case VBE_DISPI_INDEX_BPP: diff -Nru xen-4.4.2/debian/patches/xsa179-qemut-4.4-0005-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch xen-4.4.2/debian/patches/xsa179-qemut-4.4-0005-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch --- xen-4.4.2/debian/patches/xsa179-qemut-4.4-0005-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa179-qemut-4.4-0005-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch 2016-06-07 14:00:07.000000000 +0000 @@ -0,0 +1,83 @@ +From 0b0cf8110e97b0cbd0da73d11163e26978822757 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 26 Apr 2016 14:48:06 +0200 +Subject: [PATCH 5/5] vga: make sure vga register setup for vbe stays intact + (CVE-2016-3712). + +Call vbe_update_vgaregs() when the guest touches GFX, SEQ or CRT +registers, to make sure the vga registers will always have the +values needed by vbe mode. This makes sure the sanity checks +applied by vbe_fixup_regs() are effective. + +Without this guests can muck with shift_control, can turn on planar +vga modes or text mode emulation while VBE is active, making qemu +take code paths meant for CGA compatibility, but with the very +large display widths and heigts settable using VBE registers. + +Which is good for one or another buffer overflow. Not that +critical as they typically read overflows happening somewhere +in the display code. So guests can DoS by crashing qemu with a +segfault, but it is probably not possible to break out of the VM. + +Fixes: CVE-2016-3712 +Reported-by: Zuozhi Fzz +Reported-by: P J P +Signed-off-by: Gerd Hoffmann +[Backport to qemu-xen-tradition] +Signed-off-by: Andrew Cooper +--- + hw/vga.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c +index b1b501b..5778c7d 100644 +--- a/qemu/hw/vga.c ++++ b/qemu/hw/vga.c +@@ -160,6 +160,8 @@ static uint32_t expand4[256]; + static uint16_t expand2[256]; + static uint8_t expand4to8[16]; + ++static void vbe_update_vgaregs(VGAState *s); ++ + static inline bool vbe_enabled(VGAState *s) + { + return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED; +@@ -449,6 +451,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) + printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); + #endif + s->sr[s->sr_index] = val & sr_mask[s->sr_index]; ++ vbe_update_vgaregs(s); + if (s->sr_index == 1) s->update_retrace_info(s); + break; + case 0x3c7: +@@ -477,6 +480,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) + printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); + #endif + s->gr[s->gr_index] = val & gr_mask[s->gr_index]; ++ vbe_update_vgaregs(s); + break; + case 0x3b4: + case 0x3d4: +@@ -490,8 +494,10 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) + /* handle CR0-7 protection */ + if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) { + /* can always write bit 4 of CR7 */ +- if (s->cr_index == 7) ++ if (s->cr_index == 7) { + s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); ++ vbe_update_vgaregs(s); ++ } + return; + } + switch(s->cr_index) { +@@ -507,6 +513,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) + s->cr[s->cr_index] = val; + break; + } ++ vbe_update_vgaregs(s); + + switch(s->cr_index) { + case 0x00: +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa180-qemut.patch xen-4.4.2/debian/patches/xsa180-qemut.patch --- xen-4.4.2/debian/patches/xsa180-qemut.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa180-qemut.patch 2016-06-07 14:01:20.000000000 +0000 @@ -0,0 +1,88 @@ +From 7490dab5c1a01b1623e9d87bdc653cb4f963dd8a Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Thu, 19 May 2016 19:38:35 +0100 +Subject: [PATCH] main loop: Big hammer to fix logfile disk DoS in Xen setups + +Each time round the main loop, we now fstat stderr. If it is too big, +we dup2 /dev/null onto it. This is not a very pretty patch but it is +very simple, easy to see that it's correct, and has a low risk of +collateral damage. + +The limit is 1Mby by default but can be adjusted by setting a new +environment variable. + +This fixes CVE-2014-3672. + +Signed-off-by: Ian Jackson +Tested-by: Ian Jackson +--- + vl.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/qemu/vl.c b/qemu/vl.c +index c864e7d..d7ef742 100644 +--- a/qemu/vl.c ++++ b/qemu/vl.c +@@ -3752,6 +3752,50 @@ static void host_main_loop_wait(int *timeout) + } + #endif + ++static void check_cve_2014_3672_xen(void) ++{ ++ static unsigned long limit = ~0UL; ++ const int fd = 2; ++ struct stat stab; ++ ++ if (limit == ~0UL) { ++ const char *s = getenv("XEN_QEMU_CONSOLE_LIMIT"); ++ /* XEN_QEMU_CONSOLE_LIMIT=0 means no limit */ ++ limit = s ? strtoul(s,0,0) : 1*1024*1024; ++ } ++ if (limit == 0) ++ return; ++ ++ int r = fstat(fd, &stab); ++ if (r) { ++ perror("fstat stderr (for CVE-2014-3672 check)"); ++ exit(-1); ++ } ++ if (!S_ISREG(stab.st_mode)) ++ return; ++ if (stab.st_size <= limit) ++ return; ++ ++ /* oh dear */ ++ fprintf(stderr,"\r\n" ++ "Closing stderr due to CVE-2014-3672 limit. " ++ " Set XEN_QEMU_CONSOLE_LIMIT to number of bytes to override," ++ " or 0 for no limit.\n"); ++ fflush(stderr); ++ ++ int nfd = open("/dev/null", O_WRONLY); ++ if (nfd < 0) { ++ perror("open /dev/null (for CVE-2014-3672 check)"); ++ exit(-1); ++ } ++ r = dup2(nfd, fd); ++ if (r != fd) { ++ perror("dup2 /dev/null (for CVE-2014-3672 check)"); ++ exit(-1); ++ } ++ close(nfd); ++} ++ + void main_loop_wait(int timeout) + { + IOHandlerRecord *ioh; +@@ -3763,6 +3807,8 @@ void main_loop_wait(int timeout) + + host_main_loop_wait(&timeout); + ++ check_cve_2014_3672_xen(); ++ + /* poll any events */ + /* XXX: separate device handlers from system ones */ + nfds = -1; +-- +1.7.10.4 + diff -Nru xen-4.4.2/debian/patches/xsa181-4.4.patch xen-4.4.2/debian/patches/xsa181-4.4.patch --- xen-4.4.2/debian/patches/xsa181-4.4.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa181-4.4.patch 2016-06-07 14:04:45.000000000 +0000 @@ -0,0 +1,38 @@ +From 605a2711c411247920116a5026e772815b1168cd Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Thu, 2 Jun 2016 14:19:00 +0100 +Subject: [PATCH] xen/arm: Don't free p2m->first_level in p2m_teardown() before + it has been allocated + +If p2m_init() didn't complete successfully, (e.g. due to VMID +exhaustion), p2m_teardown() is called and unconditionally tries to free +p2m->first_level before it has been allocated. free_domheap_pages() doesn't +tolerate NULL pointers. + +This is XSA-181 + +Reported-by: Aaron Cornelius +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich +Reviewed-by: Julien Grall +--- + xen/arch/arm/p2m.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c +index aff7a2c..9cf6f91 100644 +--- a/xen/arch/arm/p2m.c ++++ b/xen/arch/arm/p2m.c +@@ -615,7 +615,8 @@ void p2m_teardown(struct domain *d) + while ( (pg = page_list_remove_head(&p2m->pages)) ) + free_domheap_page(pg); + +- free_domheap_pages(p2m->first_level, P2M_FIRST_ORDER); ++ if ( p2m->first_level ) ++ free_domheap_pages(p2m->first_level, P2M_FIRST_ORDER); + + p2m->first_level = NULL; + +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa182-4.5.patch xen-4.4.2/debian/patches/xsa182-4.5.patch --- xen-4.4.2/debian/patches/xsa182-4.5.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa182-4.5.patch 2016-10-06 14:01:23.000000000 +0000 @@ -0,0 +1,102 @@ +From 798c1498f764bfaa7b0b955bab40b01b0610d372 Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Mon, 11 Jul 2016 14:32:03 +0100 +Subject: [PATCH] x86/pv: Remove unsafe bits from the mod_l?_entry() fastpath + +All changes in writeability and cacheability must go through full +re-validation. + +Rework the logic as a whitelist, to make it clearer to follow. + +This is XSA-182 + +Reported-by: Jérémie Boutoille +Signed-off-by: Andrew Cooper +Reviewed-by: Tim Deegan +--- + xen/arch/x86/mm.c | 28 ++++++++++++++++------------ + xen/include/asm-x86/page.h | 1 + + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c +index b4c4fa4..a68a1ab 100644 +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -1695,6 +1695,14 @@ static inline int update_intpte(intpte_t *p, + _t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \ + (_m), (_v), (_ad)) + ++/* ++ * PTE flags that a guest may change without re-validating the PTE. ++ * All other bits affect translation, caching, or Xen's safety. ++ */ ++#define FASTPATH_FLAG_WHITELIST \ ++ (_PAGE_NX_BIT | _PAGE_AVAIL_HIGH | _PAGE_AVAIL | _PAGE_GLOBAL | \ ++ _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_USER) ++ + /* Update the L1 entry at pl1e to new value nl1e. */ + static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, + unsigned long gl1mfn, int preserve_ad, +@@ -1735,9 +1743,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, + return -EINVAL; + } + +- /* Fast path for identical mapping, r/w, presence, and cachability. */ +- if ( !l1e_has_changed(ol1e, nl1e, +- PAGE_CACHE_ATTRS | _PAGE_RW | _PAGE_PRESENT) ) ++ /* Fast path for sufficiently-similar mappings. */ ++ if ( !l1e_has_changed(ol1e, nl1e, ~FASTPATH_FLAG_WHITELIST) ) + { + adjust_guest_l1e(nl1e, pt_dom); + if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu, +@@ -1819,11 +1826,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e, + return -EINVAL; + } + +- /* Fast path for identical mapping and presence. */ +- if ( !l2e_has_changed(ol2e, nl2e, +- unlikely(opt_allow_superpage) +- ? _PAGE_PSE | _PAGE_RW | _PAGE_PRESENT +- : _PAGE_PRESENT) ) ++ /* Fast path for sufficiently-similar mappings. */ ++ if ( !l2e_has_changed(ol2e, nl2e, ~FASTPATH_FLAG_WHITELIST) ) + { + adjust_guest_l2e(nl2e, d); + if ( UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, vcpu, preserve_ad) ) +@@ -1888,8 +1892,8 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, + return -EINVAL; + } + +- /* Fast path for identical mapping and presence. */ +- if ( !l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT) ) ++ /* Fast path for sufficiently-similar mappings. */ ++ if ( !l3e_has_changed(ol3e, nl3e, ~FASTPATH_FLAG_WHITELIST) ) + { + adjust_guest_l3e(nl3e, d); + rc = UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, vcpu, preserve_ad); +@@ -1952,8 +1956,8 @@ static int mod_l4_entry(l4_pgentry_t *pl4e, + return -EINVAL; + } + +- /* Fast path for identical mapping and presence. */ +- if ( !l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT) ) ++ /* Fast path for sufficiently-similar mappings. */ ++ if ( !l4e_has_changed(ol4e, nl4e, ~FASTPATH_FLAG_WHITELIST) ) + { + adjust_guest_l4e(nl4e, d); + rc = UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, vcpu, preserve_ad); +diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h +index 6dc9646..03c024c 100644 +--- a/xen/include/asm-x86/page.h ++++ b/xen/include/asm-x86/page.h +@@ -308,6 +308,7 @@ void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t); + #define _PAGE_AVAIL2 _AC(0x800,U) + #define _PAGE_AVAIL _AC(0xE00,U) + #define _PAGE_PSE_PAT _AC(0x1000,U) ++#define _PAGE_AVAIL_HIGH (_AC(0x7ff, U) << 12) + /* non-architectural flags */ + #define _PAGE_PAGED 0x2000U + #define _PAGE_SHARED 0x4000U +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa184-qemut-master.patch xen-4.4.2/debian/patches/xsa184-qemut-master.patch --- xen-4.4.2/debian/patches/xsa184-qemut-master.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa184-qemut-master.patch 2016-10-06 14:02:21.000000000 +0000 @@ -0,0 +1,43 @@ +From 17d8c4e47dfb41cb6778520ff2eab7a11fe12dfd Mon Sep 17 00:00:00 2001 +From: P J P +Date: Tue, 26 Jul 2016 15:31:59 +0100 +Subject: [PATCH] virtio: error out if guest exceeds virtqueue size + +A broken or malicious guest can submit more requests than the virtqueue +size permits. + +The guest can submit requests without bothering to wait for completion +and is therefore not bound by virtqueue size. This requires reusing +vring descriptors in more than one request, which is incorrect but +possible. Processing a request allocates a VirtQueueElement and +therefore causes unbounded memory allocation controlled by the guest. + +Exit with an error if the guest provides more requests than the +virtqueue size permits. This bounds memory allocation and makes the +buggy guest visible to the user. + +Reported-by: Zhenhao Hong +Signed-off-by: Stefan Hajnoczi +--- + hw/virtio.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c +index c26feff..42897bf 100644 +--- a/qemu/hw/virtio.c ++++ b/qemu/hw/virtio.c +@@ -421,6 +421,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) + /* When we start there are none of either input nor output. */ + elem->out_num = elem->in_num = 0; + ++ if (vq->inuse >= vq->vring.num) { ++ fprintf(stderr, "Virtqueue size exceeded"); ++ exit(1); ++ } ++ + i = head = virtqueue_get_head(vq, vq->last_avail_idx++); + do { + struct iovec *sg; +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa185.patch xen-4.4.2/debian/patches/xsa185.patch --- xen-4.4.2/debian/patches/xsa185.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa185.patch 2016-10-06 14:02:50.000000000 +0000 @@ -0,0 +1,38 @@ +From 30aba4992b18245c436f16df7326a16c01a51570 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Mon, 8 Aug 2016 10:58:12 +0100 +Subject: x86/32on64: don't allow recursive page tables from L3 + +L3 entries are special in PAE mode, and hence can't reasonably be used +for setting up recursive (and hence linear) page table mappings. Since +abuse is possible when the guest in fact gets run on 4-level page +tables, this needs to be excluded explicitly. + +This is XSA-185. + +Reported-by: Jérémie Boutoille +Reported-by: 栾尚聪(好风) +Signed-off-by: Jan Beulich +Reviewed-by: Andrew Cooper +--- + xen/arch/x86/mm.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c +index 109b8be..69b8b8d 100644 +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -1122,7 +1122,9 @@ get_page_from_l3e( + + rc = get_page_and_type_from_pagenr( + l3e_get_pfn(l3e), PGT_l2_page_table, d, partial, 1); +- if ( unlikely(rc == -EINVAL) && get_l3_linear_pagetable(l3e, pfn, d) ) ++ if ( unlikely(rc == -EINVAL) && ++ !is_pv_32bit_domain(d) && ++ get_l3_linear_pagetable(l3e, pfn, d) ) + rc = 0; + + return rc; +-- +2.1.4 + diff -Nru xen-4.4.2/debian/patches/xsa187-4.4-0002-x86-segment-Bounds-check-accesses-to-emulation-ctx.patch xen-4.4.2/debian/patches/xsa187-4.4-0002-x86-segment-Bounds-check-accesses-to-emulation-ctx.patch --- xen-4.4.2/debian/patches/xsa187-4.4-0002-x86-segment-Bounds-check-accesses-to-emulation-ctx.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa187-4.4-0002-x86-segment-Bounds-check-accesses-to-emulation-ctx.patch 2016-10-06 15:51:46.000000000 +0000 @@ -0,0 +1,148 @@ +From: Andrew Cooper +Subject: x86/segment: Bounds check accesses to emulation ctxt->seg_reg[] + +HVM HAP codepaths have space for all segment registers in the seg_reg[] +cache (with x86_seg_none still risking an array overrun), while the shadow +codepaths only have space for the user segments. + +Range check the input segment of *_get_seg_reg() against the size of the array +used to cache the results, to avoid overruns in the case that the callers +don't filter their input suitably. + +Subsume the is_x86_user_segment(seg) checks from the shadow code, which were +an incomplete attempt at range checking, and are now superceeded. Make +hvm_get_seg_reg() static, as it is not used outside of shadow/common.c + +No functional change, but far easier to reason that no overflow is possible. + +Reported-by: Andrew Cooper +Signed-off-by: Andrew Cooper +Acked-by: Tim Deegan +Acked-by: Jan Beulich + +Index: xen-4.4.2/xen/arch/x86/hvm/emulate.c +=================================================================== +--- xen-4.4.2.orig/xen/arch/x86/hvm/emulate.c 2016-10-06 17:51:37.120009197 +0200 ++++ xen-4.4.2/xen/arch/x86/hvm/emulate.c 2016-10-06 17:51:37.116009197 +0200 +@@ -424,6 +424,8 @@ static int hvmemul_virtual_to_linear( + *reps = min_t(unsigned long, *reps, 4096); + + reg = hvmemul_get_seg_reg(seg, hvmemul_ctxt); ++ if ( IS_ERR(reg) ) ++ return -PTR_ERR(reg); + + if ( (hvmemul_ctxt->ctxt.regs->eflags & X86_EFLAGS_DF) && (*reps > 1) ) + { +@@ -908,6 +910,10 @@ static int hvmemul_read_segment( + struct hvm_emulate_ctxt *hvmemul_ctxt = + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt); ++ ++ if ( IS_ERR(sreg) ) ++ return -PTR_ERR(sreg); ++ + memcpy(reg, sreg, sizeof(struct segment_register)); + return X86EMUL_OKAY; + } +@@ -921,6 +927,9 @@ static int hvmemul_write_segment( + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt); + ++ if ( IS_ERR(sreg) ) ++ return -PTR_ERR(sreg); ++ + memcpy(sreg, reg, sizeof(struct segment_register)); + __set_bit(seg, &hvmemul_ctxt->seg_reg_dirty); + +@@ -1284,10 +1293,17 @@ void hvm_emulate_writeback( + } + } + ++/* ++ * Callers which pass a known in-range x86_segment can rely on the return ++ * pointer being valid. Other callers must explicitly check for errors. ++ */ + struct segment_register *hvmemul_get_seg_reg( + enum x86_segment seg, + struct hvm_emulate_ctxt *hvmemul_ctxt) + { ++ if ( seg < 0 || seg >= ARRAY_SIZE(hvmemul_ctxt->seg_reg) ) ++ return ERR_PTR(-X86EMUL_UNHANDLEABLE); ++ + if ( !__test_and_set_bit(seg, &hvmemul_ctxt->seg_reg_accessed) ) + hvm_get_segment_register(current, seg, &hvmemul_ctxt->seg_reg[seg]); + return &hvmemul_ctxt->seg_reg[seg]; +Index: xen-4.4.2/xen/arch/x86/mm/shadow/common.c +=================================================================== +--- xen-4.4.2.orig/xen/arch/x86/mm/shadow/common.c 2016-10-06 17:51:37.120009197 +0200 ++++ xen-4.4.2/xen/arch/x86/mm/shadow/common.c 2016-10-06 17:51:37.116009197 +0200 +@@ -120,10 +120,19 @@ __initcall(shadow_audit_key_init); + /* x86 emulator support for the shadow code + */ + ++/* ++ * Callers which pass a known in-range x86_segment can rely on the return ++ * pointer being valid. Other callers must explicitly check for errors. ++ */ + struct segment_register *hvm_get_seg_reg( + enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt) + { +- struct segment_register *seg_reg = &sh_ctxt->seg_reg[seg]; ++ struct segment_register *seg_reg; ++ ++ if ( seg < 0 || seg >= ARRAY_SIZE(sh_ctxt->seg_reg) ) ++ return ERR_PTR(-X86EMUL_UNHANDLEABLE); ++ ++ seg_reg = &sh_ctxt->seg_reg[seg]; + if ( !__test_and_set_bit(seg, &sh_ctxt->valid_seg_regs) ) + hvm_get_segment_register(current, seg, seg_reg); + return seg_reg; +@@ -140,14 +149,9 @@ static int hvm_translate_linear_addr( + struct segment_register *reg; + int okay; + +- /* +- * Can arrive here with non-user segments. However, no such cirucmstance +- * is part of a legitimate pagetable update, so fail the emulation. +- */ +- if ( !is_x86_user_segment(seg) ) +- return X86EMUL_UNHANDLEABLE; +- + reg = hvm_get_seg_reg(seg, sh_ctxt); ++ if ( IS_ERR(reg) ) ++ return -PTR_ERR(reg); + + okay = hvm_virtual_to_linear_addr( + seg, reg, offset, bytes, access_type, sh_ctxt->ctxt.addr_size, paddr); +@@ -249,9 +253,6 @@ hvm_emulate_write(enum x86_segment seg, + unsigned long addr; + int rc; + +- if ( !is_x86_user_segment(seg) ) +- return X86EMUL_UNHANDLEABLE; +- + /* How many emulations could we save if we unshadowed on stack writes? */ + if ( seg == x86_seg_ss ) + perfc_incr(shadow_fault_emulate_stack); +@@ -279,9 +280,6 @@ hvm_emulate_cmpxchg(enum x86_segment seg + unsigned long addr, old[2], new[2]; + int rc; + +- if ( !is_x86_user_segment(seg) ) +- return X86EMUL_UNHANDLEABLE; +- + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) +Index: xen-4.4.2/xen/include/asm-x86/hvm/emulate.h +=================================================================== +--- xen-4.4.2.orig/xen/include/asm-x86/hvm/emulate.h 2016-10-06 17:51:37.120009197 +0200 ++++ xen-4.4.2/xen/include/asm-x86/hvm/emulate.h 2016-10-06 17:51:37.116009197 +0200 +@@ -13,6 +13,7 @@ + #define __ASM_X86_HVM_EMULATE_H__ + + #include ++#include + #include + + struct hvm_emulate_ctxt { diff -Nru xen-4.4.2/debian/patches/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch xen-4.4.2/debian/patches/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch --- xen-4.4.2/debian/patches/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch 2016-10-06 15:49:24.000000000 +0000 @@ -0,0 +1,42 @@ +From: Andrew Cooper +Subject: x86/shadow: Avoid overflowing sh_ctxt->seg_reg[] + +hvm_get_seg_reg() does not perform a range check on its input segment, calls +hvm_get_segment_register() and writes straight into sh_ctxt->seg_reg[]. + +x86_seg_none is outside the bounds of sh_ctxt->seg_reg[], and will hit a BUG() +in {vmx,svm}_get_segment_register(). + +HVM guests running with shadow paging can end up performing a virtual to +linear translation with x86_seg_none. This is used for addresses which are +already linear. However, none of this is a legitimate pagetable update, so +fail the emulation in such a case. + +This is XSA-187 + +Reported-by: Andrew Cooper +Signed-off-by: Andrew Cooper +Reviewed-by: Tim Deegan + +--- a/xen/arch/x86/mm/shadow/common.c ++++ b/xen/arch/x86/mm/shadow/common.c +@@ -140,9 +140,18 @@ static int hvm_translate_linear_addr( + struct sh_emulate_ctxt *sh_ctxt, + unsigned long *paddr) + { +- struct segment_register *reg = hvm_get_seg_reg(seg, sh_ctxt); ++ struct segment_register *reg; + int okay; + ++ /* ++ * Can arrive here with non-user segments. However, no such cirucmstance ++ * is part of a legitimate pagetable update, so fail the emulation. ++ */ ++ if ( !is_x86_user_segment(seg) ) ++ return X86EMUL_UNHANDLEABLE; ++ ++ reg = hvm_get_seg_reg(seg, sh_ctxt); ++ + okay = hvm_virtual_to_linear_addr( + seg, reg, offset, bytes, access_type, sh_ctxt->ctxt.addr_size, paddr); + diff -Nru xen-4.4.2/debian/patches/xsa188.patch xen-4.4.2/debian/patches/xsa188.patch --- xen-4.4.2/debian/patches/xsa188.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa188.patch 2016-10-06 14:04:34.000000000 +0000 @@ -0,0 +1,23 @@ +evtchn-fifo: prevent use after free + +evtchn_fifo_init_control() calls evtchn_fifo_destroy() on an error +path, leading to cleanup_event_array() which frees d->evtchn_fifo +without also clearing the pointer. Otoh the bulk of +evtchn_fifo_init_control() is dependent on d->evtchn_fifo being NULL. + +This is XSA-188. + +Reported-by: Mikhail V Gorobets +Suggested-by: Mikhail V Gorobets +Signed-off-by: Jan Beulich + +--- a/xen/common/event_fifo.c ++++ b/xen/common/event_fifo.c +@@ -482,6 +482,7 @@ static void cleanup_event_array(struct d + for ( i = 0; i < EVTCHN_FIFO_MAX_EVENT_ARRAY_PAGES; i++ ) + unmap_guest_page(d->evtchn_fifo->event_array[i]); + xfree(d->evtchn_fifo); ++ d->evtchn_fifo = NULL; + } + + static void setup_ports(struct domain *d) diff -Nru xen-4.4.2/debian/patches/xsa190-4.5.patch xen-4.4.2/debian/patches/xsa190-4.5.patch --- xen-4.4.2/debian/patches/xsa190-4.5.patch 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.4.2/debian/patches/xsa190-4.5.patch 2016-10-06 14:04:47.000000000 +0000 @@ -0,0 +1,163 @@ +x86emul: honor guest CR0.TS and CR0.EM + +We must not emulate any instructions accessing respective registers +when either of these flags is set in the guest view of the register, or +else we may do so on data not belonging to the guest's current task. + +Being architecturally required behavior, the logic gets placed in the +instruction emulator instead of hvmemul_get_fpu(). It should be noted, +though, that hvmemul_get_fpu() being the only current handler for the +get_fpu() callback, we don't have an active problem with CR4: Both +CR4.OSFXSR and CR4.OSXSAVE get handled as necessary by that function. + +This is XSA-190. + +Signed-off-by: Jan Beulich +Reviewed-by: Andrew Cooper + +--- a/tools/tests/x86_emulator/test_x86_emulator.c ++++ b/tools/tests/x86_emulator/test_x86_emulator.c +@@ -129,6 +129,22 @@ static inline uint64_t xgetbv(uint32_t x + (ebx & (1U << 5)) != 0; \ + }) + ++static int read_cr( ++ unsigned int reg, ++ unsigned long *val, ++ struct x86_emulate_ctxt *ctxt) ++{ ++ /* Fake just enough state for the emulator's _get_fpu() to be happy. */ ++ switch ( reg ) ++ { ++ case 0: ++ *val = 0x00000001; /* PE */ ++ return X86EMUL_OKAY; ++ } ++ ++ return X86EMUL_UNHANDLEABLE; ++} ++ + int get_fpu( + void (*exception_callback)(void *, struct cpu_user_regs *), + void *exception_callback_arg, +@@ -160,6 +176,7 @@ static struct x86_emulate_ops emulops = + .write = write, + .cmpxchg = cmpxchg, + .cpuid = cpuid, ++ .read_cr = read_cr, + .get_fpu = get_fpu, + }; + +--- a/xen/arch/x86/hvm/emulate.c ++++ b/xen/arch/x86/hvm/emulate.c +@@ -1192,6 +1192,7 @@ static int hvmemul_get_fpu( + switch ( type ) + { + case X86EMUL_FPU_fpu: ++ case X86EMUL_FPU_wait: + break; + case X86EMUL_FPU_mmx: + if ( !cpu_has_mmx ) +@@ -1199,7 +1200,6 @@ static int hvmemul_get_fpu( + break; + case X86EMUL_FPU_xmm: + if ( !cpu_has_xmm || +- (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_EM) || + !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) ) + return X86EMUL_UNHANDLEABLE; + break; +--- a/xen/arch/x86/x86_emulate/x86_emulate.c ++++ b/xen/arch/x86/x86_emulate/x86_emulate.c +@@ -373,6 +373,9 @@ typedef union { + + /* Control register flags. */ + #define CR0_PE (1<<0) ++#define CR0_MP (1<<1) ++#define CR0_EM (1<<2) ++#define CR0_TS (1<<3) + #define CR4_TSD (1<<2) + + /* EFLAGS bit definitions. */ +@@ -400,6 +403,7 @@ typedef union { + #define EXC_OF 4 + #define EXC_BR 5 + #define EXC_UD 6 ++#define EXC_NM 7 + #define EXC_TS 10 + #define EXC_NP 11 + #define EXC_SS 12 +@@ -684,10 +688,45 @@ static void fpu_handle_exception(void *_ + regs->eip += fic->insn_bytes; + } + ++static int _get_fpu( ++ enum x86_emulate_fpu_type type, ++ struct fpu_insn_ctxt *fic, ++ struct x86_emulate_ctxt *ctxt, ++ const struct x86_emulate_ops *ops) ++{ ++ int rc; ++ ++ fic->exn_raised = 0; ++ ++ fail_if(!ops->get_fpu); ++ rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt); ++ ++ if ( rc == X86EMUL_OKAY ) ++ { ++ unsigned long cr0; ++ ++ fail_if(!ops->read_cr); ++ rc = ops->read_cr(0, &cr0, ctxt); ++ if ( rc != X86EMUL_OKAY ) ++ return rc; ++ if ( cr0 & CR0_EM ) ++ { ++ generate_exception_if(type == X86EMUL_FPU_fpu, EXC_NM, -1); ++ generate_exception_if(type == X86EMUL_FPU_mmx, EXC_UD, -1); ++ generate_exception_if(type == X86EMUL_FPU_xmm, EXC_UD, -1); ++ } ++ generate_exception_if((cr0 & CR0_TS) && ++ (type != X86EMUL_FPU_wait || (cr0 & CR0_MP)), ++ EXC_NM, -1); ++ } ++ ++ done: ++ return rc; ++} ++ + #define get_fpu(_type, _fic) \ +-do{ (_fic)->exn_raised = 0; \ +- fail_if(ops->get_fpu == NULL); \ +- rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \ ++do { \ ++ rc = _get_fpu(_type, _fic, ctxt, ops); \ + if ( rc ) goto done; \ + } while (0) + #define put_fpu(_fic) \ +@@ -2491,8 +2530,14 @@ x86_emulate( + } + + case 0x9b: /* wait/fwait */ +- emulate_fpu_insn("fwait"); ++ { ++ struct fpu_insn_ctxt fic = { .insn_bytes = 1 }; ++ ++ get_fpu(X86EMUL_FPU_wait, &fic); ++ asm volatile ( "fwait" ::: "memory" ); ++ put_fpu(&fic); + break; ++ } + + case 0x9c: /* pushf */ + src.val = _regs.eflags; +--- a/xen/arch/x86/x86_emulate/x86_emulate.h ++++ b/xen/arch/x86/x86_emulate/x86_emulate.h +@@ -114,6 +114,7 @@ struct __packed segment_register { + /* FPU sub-types which may be requested via ->get_fpu(). */ + enum x86_emulate_fpu_type { + X86EMUL_FPU_fpu, /* Standard FPU coprocessor instruction set */ ++ X86EMUL_FPU_wait, /* WAIT/FWAIT instruction */ + X86EMUL_FPU_mmx, /* MMX instruction set (%mm0-%mm7) */ + X86EMUL_FPU_xmm, /* SSE instruction set (%xmm0-%xmm7/15) */ + X86EMUL_FPU_ymm /* AVX/XOP instruction set (%ymm0-%ymm7/15) */