From owner-svn-ports-head@FreeBSD.ORG Thu Jun 11 18:26:49 2015 Return-Path: Delivered-To: svn-ports-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id F1FDBC3E; Thu, 11 Jun 2015 18:26:48 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DE21A1D35; Thu, 11 Jun 2015 18:26:48 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t5BIQm43020984; Thu, 11 Jun 2015 18:26:48 GMT (envelope-from bapt@FreeBSD.org) Received: (from bapt@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t5BIQkUk020960; Thu, 11 Jun 2015 18:26:46 GMT (envelope-from bapt@FreeBSD.org) Message-Id: <201506111826.t5BIQkUk020960@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: bapt set sender to bapt@FreeBSD.org using -f From: Baptiste Daroussin Date: Thu, 11 Jun 2015 18:26:46 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r389243 - in head/sysutils/xen-tools: . files X-SVN-Group: ports-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jun 2015 18:26:49 -0000 Author: bapt Date: Thu Jun 11 18:26:45 2015 New Revision: 389243 URL: https://svnweb.freebsd.org/changeset/ports/389243 Log: Fix multiple security issues Remove previous XSA-133 fix for consistency Security: XSA-119 / CVE-2015-2152 Security: XSA-125 / CVE-2015-2752 Security: XSA-126 / CVE-2015-2756 Security: XSA-128 / CVE-2015-4103 Security: XSA-129 / CVE-2015-4104 Security: XSA-130 / CVE-2015-4105 Security: XSA-131 / CVE-2015-4106 Security: XSA-133 / CVE-2015-3456 Security: XSA-135 / CVE-2015-3209 Added: head/sysutils/xen-tools/files/xsa119-unstable.patch (contents, props changed) head/sysutils/xen-tools/files/xsa125.patch (contents, props changed) head/sysutils/xen-tools/files/xsa126-qemut.patch (contents, props changed) head/sysutils/xen-tools/files/xsa126-qemuu.patch (contents, props changed) head/sysutils/xen-tools/files/xsa128-qemut.patch (contents, props changed) head/sysutils/xen-tools/files/xsa128-qemuu.patch (contents, props changed) head/sysutils/xen-tools/files/xsa129-qemut.patch (contents, props changed) head/sysutils/xen-tools/files/xsa129-qemuu.patch (contents, props changed) head/sysutils/xen-tools/files/xsa130-qemut.patch (contents, props changed) head/sysutils/xen-tools/files/xsa130-qemuu.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-1.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-2.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-3.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-4.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-5.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-6.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-7.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemut-8.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-1.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-2.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-3.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-4.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-5.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-6.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-7.patch (contents, props changed) head/sysutils/xen-tools/files/xsa131-qemuu-8.patch (contents, props changed) head/sysutils/xen-tools/files/xsa133-qemut.patch (contents, props changed) head/sysutils/xen-tools/files/xsa133-qemuu.patch (contents, props changed) head/sysutils/xen-tools/files/xsa135-qemut-1.patch (contents, props changed) head/sysutils/xen-tools/files/xsa135-qemut-2.patch (contents, props changed) head/sysutils/xen-tools/files/xsa135-qemuu-4.5-1.patch (contents, props changed) head/sysutils/xen-tools/files/xsa135-qemuu-4.5-2.patch (contents, props changed) Modified: head/sysutils/xen-tools/Makefile Modified: head/sysutils/xen-tools/Makefile ============================================================================== --- head/sysutils/xen-tools/Makefile Thu Jun 11 18:14:48 2015 (r389242) +++ head/sysutils/xen-tools/Makefile Thu Jun 11 18:26:45 2015 (r389243) @@ -3,7 +3,7 @@ PORTNAME= xen PKGNAMESUFFIX= -tools PORTVERSION= 4.5.0 -PORTREVISION= 5 +PORTREVISION= 6 CATEGORIES= sysutils emulators MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/ \ http://code.coreboot.org/p/seabios/downloads/get/:seabios @@ -46,6 +46,10 @@ QEMU_ARGS= --disable-gtk \ --disable-tools \ --disable-curl \ --cxx=c++ + +EXTRA_PATCHES= ${FILESDIR}/xsa119-unstable.patch:-p1 \ + ${FILESDIR}/xsa125.patch:-p1 + CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}" SHEBANG_FILES= tools/misc/xencov_split \ tools/misc/xen-ringwatch @@ -71,6 +75,14 @@ post-patch: ${WRKSRC}/tools/libxl/libxl_dm.c \ ${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \ ${WRKSRC}/docs/man/* + @for p in ${FILESDIR}/*qemut*.patch; do \ + ${ECHO_CMD} "====> Applying $${p##*/}" ; \ + patch -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen-traditional ; \ + done + @for p in ${FILESDIR}/*qemuu*.patch; do \ + ${ECHO_CMD} "====> Applying $${p##*/}" ; \ + patch -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \ + done post-install: ${MKDIR} ${STAGEDIR}/var/run/xen Added: head/sysutils/xen-tools/files/xsa119-unstable.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa119-unstable.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,99 @@ +From f433bfafbaf7d8a41c4c27aa3e8e78b1ab900b69 Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Fri, 20 Feb 2015 14:41:09 +0000 +Subject: [PATCH] tools: libxl: Explicitly disable graphics backends on qemu + cmdline + +By default qemu will try to create some sort of backend for the +emulated VGA device, either SDL or VNC. + +However when the user specifies sdl=0 and vnc=0 in their configuration +libxl was not explicitly disabling either backend, which could lead to +one unexpectedly running. + +If either sdl=1 or vnc=1 is configured then both before and after this +change only the backends which are explicitly enabled are configured, +i.e. this issue only occurs when all backends are supposed to have +been disabled. + +This affects qemu-xen and qemu-xen-traditional differently. + +If qemu-xen was compiled with SDL support then this would result in an +SDL window being opened if $DISPLAY is valid, or a failure to start +the guest if not. Passing "-display none" to qemu before any further +-sdl options disables this default behaviour and ensures that SDL is +only started if the libxl configuration demands it. + +If qemu-xen was compiled without SDL support then qemu would instead +start a VNC server listening on ::1 (IPv6 localhost) or 127.0.0.1 +(IPv4 localhost) with IPv6 preferred if available. Explicitly pass +"-vnc none" when vnc is not enabled in the libxl configuration to +remove this possibility. + +qemu-xen-traditional would never start a vnc backend unless asked. +However by default it will start an SDL backend, the way to disable +this is to pass a -vnc option. In other words passing "-vnc none" will +disable both vnc and sdl by default. sdl can then be reenabled if +configured by subsequent use of the -sdl option. + +Tested with both qemu-xen and qemu-xen-traditional built with SDL +support and: + xl cr # defaults + xl cr sdl=0 vnc=0 + xl cr sdl=1 vnc=0 + xl cr sdl=0 vnc=1 + xl cr sdl=0 vnc=0 vga=\"none\" + xl cr sdl=0 vnc=0 nographic=1 +with both valid and invalid $DISPLAY. + +This is XSA-119. + +Reported-by: Sander Eikelenboom +Signed-off-by: Ian Campbell +Acked-by: Ian Jackson +--- + tools/libxl/libxl_dm.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c +index 8599a6a..3b918c6 100644 +--- a/tools/libxl/libxl_dm.c ++++ b/tools/libxl/libxl_dm.c +@@ -180,7 +180,14 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc, + if (libxl_defbool_val(vnc->findunused)) { + flexarray_append(dm_args, "-vncunused"); + } +- } ++ } else ++ /* ++ * VNC is not enabled by default by qemu-xen-traditional, ++ * however passing -vnc none causes SDL to not be ++ * (unexpectedly) enabled by default. This is overridden by ++ * explicitly passing -sdl below as required. ++ */ ++ flexarray_append_pair(dm_args, "-vnc", "none"); + + if (sdl) { + flexarray_append(dm_args, "-sdl"); +@@ -522,7 +529,17 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc, + } + + flexarray_append(dm_args, vncarg); +- } ++ } else ++ /* ++ * Ensure that by default no vnc server is created. ++ */ ++ flexarray_append_pair(dm_args, "-vnc", "none"); ++ ++ /* ++ * Ensure that by default no display backend is created. Further ++ * options given below might then enable more. ++ */ ++ flexarray_append_pair(dm_args, "-display", "none"); + + if (sdl) { + flexarray_append(dm_args, "-sdl"); +-- +2.1.4 + Added: head/sysutils/xen-tools/files/xsa125.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa125.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,154 @@ +From 98670acc98cad5aee0e0714694a64d3b96675c36 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 19 Nov 2014 12:57:11 -0500 +Subject: [PATCH] Limit XEN_DOMCTL_memory_mapping hypercall to only process up + to 64 GFNs (or less) + +Said hypercall for large BARs can take quite a while. As such +we can require that the hypercall MUST break up the request +in smaller values. + +Another approach is to add preemption to it - whether we do the +preemption using hypercall_create_continuation or returning +EAGAIN to userspace (and have it re-invocate the call) - either +way the issue we cannot easily solve is that in 'map_mmio_regions' +if we encounter an error we MUST call 'unmap_mmio_regions' for the +whole BAR region. + +Since the preemption would re-use input fields such as nr_mfns, +first_gfn, first_mfn - we would lose the original values - +and only undo what was done in the current round (i.e. ignoring +anything that was done prior to earlier preemptions). + +Unless we re-used the return value as 'EAGAIN|nr_mfns_done<<10' but +that puts a limit (since the return value is a long) on the amount +of nr_mfns that can provided. + +This patch sidesteps this problem by: + - Setting an hard limit of nr_mfns having to be 64 or less. + - Toolstack adjusts correspondingly to the nr_mfn limit. + - If the there is an error when adding the toolstack will call the + remove operation to remove the whole region. + +The need to break this hypercall down is for large BARs can take +more than the guest (initial domain usually) time-slice. This has +the negative result in that the guest is locked out for a long +duration and is unable to act on any pending events. + +We also augment the code to return zero if nr_mfns instead +of trying to the hypercall. + +Suggested-by: Jan Beulich +Acked-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +Acked-by: Ian Campbell +--- +[v50: Simplify loop] +[v51: If max_batch_sz 1 (or less) we would return zero. Fix that] +[v52: Handle nr_mfns being zero] +[v53: Fix up return value] +--- + tools/libxc/xc_domain.c | 46 +++++++++++++++++++++++++++++++++++++++++---- + xen/common/domctl.c | 5 +++++ + xen/include/public/domctl.h | 1 + + 3 files changed, 48 insertions(+), 4 deletions(-) + +diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c +index 845d1d7..bba7672 100644 +--- a/tools/libxc/xc_domain.c ++++ b/tools/libxc/xc_domain.c +@@ -1988,6 +1988,8 @@ int xc_domain_memory_mapping( + { + DECLARE_DOMCTL; + xc_dominfo_t info; ++ int ret = 0, err; ++ unsigned long done = 0, nr, max_batch_sz; + + if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 || + info.domid != domid ) +@@ -1998,14 +2000,50 @@ int xc_domain_memory_mapping( + if ( !xc_core_arch_auto_translated_physmap(&info) ) + return 0; + ++ if ( !nr_mfns ) ++ return 0; ++ + domctl.cmd = XEN_DOMCTL_memory_mapping; + domctl.domain = domid; +- domctl.u.memory_mapping.first_gfn = first_gfn; +- domctl.u.memory_mapping.first_mfn = first_mfn; +- domctl.u.memory_mapping.nr_mfns = nr_mfns; + domctl.u.memory_mapping.add_mapping = add_mapping; ++ max_batch_sz = nr_mfns; ++ do ++ { ++ nr = min(nr_mfns - done, max_batch_sz); ++ domctl.u.memory_mapping.nr_mfns = nr; ++ domctl.u.memory_mapping.first_gfn = first_gfn + done; ++ domctl.u.memory_mapping.first_mfn = first_mfn + done; ++ err = do_domctl(xch, &domctl); ++ if ( err && errno == E2BIG ) ++ { ++ if ( max_batch_sz <= 1 ) ++ break; ++ max_batch_sz >>= 1; ++ continue; ++ } ++ /* Save the first error... */ ++ if ( !ret ) ++ ret = err; ++ /* .. and ignore the rest of them when removing. */ ++ if ( err && add_mapping != DPCI_REMOVE_MAPPING ) ++ break; + +- return do_domctl(xch, &domctl); ++ done += nr; ++ } while ( done < nr_mfns ); ++ ++ /* ++ * Undo what we have done unless unmapping, by unmapping the entire region. ++ * Errors here are ignored. ++ */ ++ if ( ret && add_mapping != DPCI_REMOVE_MAPPING ) ++ xc_domain_memory_mapping(xch, domid, first_gfn, first_mfn, nr_mfns, ++ DPCI_REMOVE_MAPPING); ++ ++ /* We might get E2BIG so many times that we never advance. */ ++ if ( !done && !ret ) ++ ret = -1; ++ ++ return ret; + } + + int xc_domain_ioport_mapping( +diff --git a/xen/common/domctl.c b/xen/common/domctl.c +index d396cc4..c2e60a7 100644 +--- a/xen/common/domctl.c ++++ b/xen/common/domctl.c +@@ -1027,6 +1027,11 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) + (gfn + nr_mfns - 1) < gfn ) /* wrap? */ + break; + ++ ret = -E2BIG; ++ /* Must break hypercall up as this could take a while. */ ++ if ( nr_mfns > 64 ) ++ break; ++ + ret = -EPERM; + if ( !iomem_access_permitted(current->domain, mfn, mfn_end) || + !iomem_access_permitted(d, mfn, mfn_end) ) +diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h +index ca0e51e..0c9f474 100644 +--- a/xen/include/public/domctl.h ++++ b/xen/include/public/domctl.h +@@ -543,6 +543,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t); + + + /* Bind machine I/O address range -> HVM address range. */ ++/* If this returns -E2BIG lower nr_mfns value. */ + /* XEN_DOMCTL_memory_mapping */ + #define DPCI_ADD_MAPPING 1 + #define DPCI_REMOVE_MAPPING 0 +-- +2.1.0 + Added: head/sysutils/xen-tools/files/xsa126-qemut.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa126-qemut.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,151 @@ +xen: limit guest control of PCI command register + +Otherwise the guest can abuse that control to cause e.g. PCIe +Unsupported Request responses (by disabling memory and/or I/O decoding +and subsequently causing [CPU side] accesses to the respective address +ranges), which (depending on system configuration) may be fatal to the +host. + +This is CVE-2015-2756 / XSA-126. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini +Acked-by: Ian Campbell + +--- a/hw/pass-through.c ++++ b/hw/pass-through.c +@@ -172,9 +172,6 @@ static int pt_word_reg_read(struct pt_de + static int pt_long_reg_read(struct pt_dev *ptdev, + struct pt_reg_tbl *cfg_entry, + uint32_t *value, uint32_t valid_mask); +-static int pt_cmd_reg_read(struct pt_dev *ptdev, +- struct pt_reg_tbl *cfg_entry, +- uint16_t *value, uint16_t valid_mask); + static int pt_bar_reg_read(struct pt_dev *ptdev, + struct pt_reg_tbl *cfg_entry, + uint32_t *value, uint32_t valid_mask); +@@ -286,9 +283,9 @@ static struct pt_reg_info_tbl pt_emu_reg + .size = 2, + .init_val = 0x0000, + .ro_mask = 0xF880, +- .emu_mask = 0x0740, ++ .emu_mask = 0x0743, + .init = pt_common_reg_init, +- .u.w.read = pt_cmd_reg_read, ++ .u.w.read = pt_word_reg_read, + .u.w.write = pt_cmd_reg_write, + .u.w.restore = pt_cmd_reg_restore, + }, +@@ -1905,7 +1902,7 @@ static int pt_dev_is_virtfn(struct pci_d + return rc; + } + +-static int pt_register_regions(struct pt_dev *assigned_device) ++static int pt_register_regions(struct pt_dev *assigned_device, uint16_t *cmd) + { + int i = 0; + uint32_t bar_data = 0; +@@ -1925,17 +1922,26 @@ static int pt_register_regions(struct pt + + /* Register current region */ + if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_IO ) ++ { + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO, + pt_ioport_map); ++ *cmd |= PCI_COMMAND_IO; ++ } + else if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_MEM_PREFETCH ) ++ { + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH, + pt_iomem_map); ++ *cmd |= PCI_COMMAND_MEMORY; ++ } + else ++ { + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM, + pt_iomem_map); ++ *cmd |= PCI_COMMAND_MEMORY; ++ } + + PT_LOG("IO region registered (size=0x%08x base_addr=0x%08x)\n", + (uint32_t)(pci_dev->size[i]), +@@ -3263,27 +3269,6 @@ static int pt_long_reg_read(struct pt_de + return 0; + } + +-/* read Command register */ +-static int pt_cmd_reg_read(struct pt_dev *ptdev, +- struct pt_reg_tbl *cfg_entry, +- uint16_t *value, uint16_t valid_mask) +-{ +- struct pt_reg_info_tbl *reg = cfg_entry->reg; +- uint16_t valid_emu_mask = 0; +- uint16_t emu_mask = reg->emu_mask; +- +- if ( ptdev->is_virtfn ) +- emu_mask |= PCI_COMMAND_MEMORY; +- if ( pt_is_iomul(ptdev) ) +- emu_mask |= PCI_COMMAND_IO; +- +- /* emulate word register */ +- valid_emu_mask = emu_mask & valid_mask; +- *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); +- +- return 0; +-} +- + /* read BAR */ + static int pt_bar_reg_read(struct pt_dev *ptdev, + struct pt_reg_tbl *cfg_entry, +@@ -3418,19 +3403,13 @@ static int pt_cmd_reg_write(struct pt_de + uint16_t writable_mask = 0; + uint16_t throughable_mask = 0; + uint16_t wr_value = *value; +- uint16_t emu_mask = reg->emu_mask; +- +- if ( ptdev->is_virtfn ) +- emu_mask |= PCI_COMMAND_MEMORY; +- if ( pt_is_iomul(ptdev) ) +- emu_mask |= PCI_COMMAND_IO; + + /* modify emulate register */ + writable_mask = ~reg->ro_mask & valid_mask; + cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); + + /* create value for writing to I/O device register */ +- throughable_mask = ~emu_mask & valid_mask; ++ throughable_mask = ~reg->emu_mask & valid_mask; + + if (*value & PCI_COMMAND_DISABLE_INTx) + { +@@ -4211,6 +4190,7 @@ static struct pt_dev * register_real_dev + struct pt_dev *assigned_device = NULL; + struct pci_dev *pci_dev; + uint8_t e_device, e_intx; ++ uint16_t cmd = 0; + char *key, *val; + int msi_translate, power_mgmt; + +@@ -4300,7 +4280,7 @@ static struct pt_dev * register_real_dev + assigned_device->dev.config[i] = pci_read_byte(pci_dev, i); + + /* Handle real device's MMIO/PIO BARs */ +- pt_register_regions(assigned_device); ++ pt_register_regions(assigned_device, &cmd); + + /* Setup VGA bios for passthroughed gfx */ + if ( setup_vga_pt(assigned_device) < 0 ) +@@ -4378,6 +4358,10 @@ static struct pt_dev * register_real_dev + } + + out: ++ if (cmd) ++ pci_write_word(pci_dev, PCI_COMMAND, ++ *(uint16_t *)(&assigned_device->dev.config[PCI_COMMAND]) | cmd); ++ + PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n" + "IRQ type = %s\n", r_bus, r_dev, r_func, + assigned_device->msi_trans_en? "MSI-INTx":"INTx"); Added: head/sysutils/xen-tools/files/xsa126-qemuu.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa126-qemuu.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,128 @@ +xen: limit guest control of PCI command register + +Otherwise the guest can abuse that control to cause e.g. PCIe +Unsupported Request responses (by disabling memory and/or I/O decoding +and subsequently causing [CPU side] accesses to the respective address +ranges), which (depending on system configuration) may be fatal to the +host. + +This is CVE-2015-2756 / XSA-126. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini +Acked-by: Ian Campbell + +--- a/hw/xen/xen_pt.c ++++ b/hw/xen/xen_pt.c +@@ -388,7 +388,7 @@ static const MemoryRegionOps ops = { + .write = xen_pt_bar_write, + }; + +-static int xen_pt_register_regions(XenPCIPassthroughState *s) ++static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd) + { + int i = 0; + XenHostPCIDevice *d = &s->real_device; +@@ -406,6 +406,7 @@ static int xen_pt_register_regions(XenPC + + if (r->type & XEN_HOST_PCI_REGION_TYPE_IO) { + type = PCI_BASE_ADDRESS_SPACE_IO; ++ *cmd |= PCI_COMMAND_IO; + } else { + type = PCI_BASE_ADDRESS_SPACE_MEMORY; + if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) { +@@ -414,6 +415,7 @@ static int xen_pt_register_regions(XenPC + if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) { + type |= PCI_BASE_ADDRESS_MEM_TYPE_64; + } ++ *cmd |= PCI_COMMAND_MEMORY; + } + + memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev, +@@ -638,6 +640,7 @@ static int xen_pt_initfn(PCIDevice *d) + XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d); + int rc = 0; + uint8_t machine_irq = 0; ++ uint16_t cmd = 0; + int pirq = XEN_PT_UNASSIGNED_PIRQ; + + /* register real device */ +@@ -672,7 +675,7 @@ static int xen_pt_initfn(PCIDevice *d) + s->io_listener = xen_pt_io_listener; + + /* Handle real device's MMIO/PIO BARs */ +- xen_pt_register_regions(s); ++ xen_pt_register_regions(s, &cmd); + + /* reinitialize each config register to be emulated */ + if (xen_pt_config_init(s)) { +@@ -736,6 +739,11 @@ static int xen_pt_initfn(PCIDevice *d) + } + + out: ++ if (cmd) { ++ xen_host_pci_set_word(&s->real_device, PCI_COMMAND, ++ pci_get_word(d->config + PCI_COMMAND) | cmd); ++ } ++ + memory_listener_register(&s->memory_listener, &address_space_memory); + memory_listener_register(&s->io_listener, &address_space_io); + XEN_PT_LOG(d, +--- a/hw/xen/xen_pt_config_init.c ++++ b/hw/xen/xen_pt_config_init.c +@@ -286,23 +286,6 @@ static int xen_pt_irqpin_reg_init(XenPCI + } + + /* Command register */ +-static int xen_pt_cmd_reg_read(XenPCIPassthroughState *s, XenPTReg *cfg_entry, +- uint16_t *value, uint16_t valid_mask) +-{ +- XenPTRegInfo *reg = cfg_entry->reg; +- uint16_t valid_emu_mask = 0; +- uint16_t emu_mask = reg->emu_mask; +- +- if (s->is_virtfn) { +- emu_mask |= PCI_COMMAND_MEMORY; +- } +- +- /* emulate word register */ +- valid_emu_mask = emu_mask & valid_mask; +- *value = XEN_PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); +- +- return 0; +-} + static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, + uint16_t *val, uint16_t dev_value, + uint16_t valid_mask) +@@ -310,18 +293,13 @@ static int xen_pt_cmd_reg_write(XenPCIPa + XenPTRegInfo *reg = cfg_entry->reg; + uint16_t writable_mask = 0; + uint16_t throughable_mask = 0; +- uint16_t emu_mask = reg->emu_mask; +- +- if (s->is_virtfn) { +- emu_mask |= PCI_COMMAND_MEMORY; +- } + + /* modify emulate register */ + writable_mask = ~reg->ro_mask & valid_mask; + cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); + + /* create value for writing to I/O device register */ +- throughable_mask = ~emu_mask & valid_mask; ++ throughable_mask = ~reg->emu_mask & valid_mask; + + if (*val & PCI_COMMAND_INTX_DISABLE) { + throughable_mask |= PCI_COMMAND_INTX_DISABLE; +@@ -605,9 +583,9 @@ static XenPTRegInfo xen_pt_emu_reg_heade + .size = 2, + .init_val = 0x0000, + .ro_mask = 0xF880, +- .emu_mask = 0x0740, ++ .emu_mask = 0x0743, + .init = xen_pt_common_reg_init, +- .u.w.read = xen_pt_cmd_reg_read, ++ .u.w.read = xen_pt_word_reg_read, + .u.w.write = xen_pt_cmd_reg_write, + }, + /* Capabilities Pointer reg */ Added: head/sysutils/xen-tools/files/xsa128-qemut.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa128-qemut.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,125 @@ +xen: properly gate host writes of modified PCI CFG contents + +The old logic didn't work as intended when an access spanned multiple +fields (for example a 32-bit access to the location of the MSI Message +Data field with the high 16 bits not being covered by any known field). +Remove it and derive which fields not to write to from the accessed +fields' emulation masks: When they're all ones, there's no point in +doing any host write. + +This fixes a secondary issue at once: We obviously shouldn't make any +host write attempt when already the host read failed. + +This is XSA-128. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini + +--- a/hw/pass-through.c ++++ b/hw/pass-through.c +@@ -454,7 +454,7 @@ static struct pt_reg_info_tbl pt_emu_reg + .offset = PCI_INTEL_OPREGION, + .size = 4, + .init_val = 0, +- .no_wb = 1, ++ .emu_mask = 0xFFFFFFFF, + .u.dw.read = pt_intel_opregion_read, + .u.dw.write = pt_intel_opregion_write, + .u.dw.restore = NULL, +@@ -657,7 +657,6 @@ static struct pt_reg_info_tbl pt_emu_reg + .init_val = 0x00000000, + .ro_mask = 0x00000003, + .emu_mask = 0xFFFFFFFF, +- .no_wb = 1, + .init = pt_common_reg_init, + .u.dw.read = pt_long_reg_read, + .u.dw.write = pt_msgaddr32_reg_write, +@@ -670,7 +669,6 @@ static struct pt_reg_info_tbl pt_emu_reg + .init_val = 0x00000000, + .ro_mask = 0x00000000, + .emu_mask = 0xFFFFFFFF, +- .no_wb = 1, + .init = pt_msgaddr64_reg_init, + .u.dw.read = pt_long_reg_read, + .u.dw.write = pt_msgaddr64_reg_write, +@@ -683,7 +681,6 @@ static struct pt_reg_info_tbl pt_emu_reg + .init_val = 0x0000, + .ro_mask = 0x0000, + .emu_mask = 0xFFFF, +- .no_wb = 1, + .init = pt_msgdata_reg_init, + .u.w.read = pt_word_reg_read, + .u.w.write = pt_msgdata_reg_write, +@@ -696,7 +693,6 @@ static struct pt_reg_info_tbl pt_emu_reg + .init_val = 0x0000, + .ro_mask = 0x0000, + .emu_mask = 0xFFFF, +- .no_wb = 1, + .init = pt_msgdata_reg_init, + .u.w.read = pt_word_reg_read, + .u.w.write = pt_msgdata_reg_write, +@@ -1524,7 +1520,7 @@ static void pt_pci_write_config(PCIDevic + uint32_t find_addr = address; + uint32_t real_offset = 0; + uint32_t valid_mask = 0xFFFFFFFF; +- uint32_t read_val = 0; ++ uint32_t read_val = 0, wb_mask; + uint8_t *ptr_val = NULL; + int emul_len = 0; + int index = 0; +@@ -1597,7 +1593,10 @@ static void pt_pci_write_config(PCIDevic + { + PT_LOG("Error: pci_read_block failed. return value[%d].\n", ret); + memset((uint8_t *)&read_val, 0xff, len); ++ wb_mask = 0; + } ++ else ++ wb_mask = 0xFFFFFFFF >> ((4 - len) << 3); + + /* pass directly to libpci for passthrough type register group */ + if (reg_grp_entry == NULL) +@@ -1620,6 +1619,11 @@ static void pt_pci_write_config(PCIDevic + valid_mask = (0xFFFFFFFF >> ((4 - emul_len) << 3)); + valid_mask <<= ((find_addr - real_offset) << 3); + ptr_val = ((uint8_t *)&val + (real_offset & 3)); ++ if (reg->emu_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { ++ wb_mask &= ~((reg->emu_mask ++ >> ((find_addr - real_offset) << 3)) ++ << ((len - emul_len) << 3)); ++ } + + /* do emulation depend on register size */ + switch (reg->size) { +@@ -1677,8 +1681,19 @@ static void pt_pci_write_config(PCIDevic + val >>= ((address & 3) << 3); + + out: +- if (!(reg && reg->no_wb)) { /* unknown regs are passed through */ +- ret = pci_write_block(pci_dev, address, (uint8_t *)&val, len); ++ for (index = 0; wb_mask; index += len) { ++ /* unknown regs are passed through */ ++ while (!(wb_mask & 0xff)) { ++ index++; ++ wb_mask >>= 8; ++ } ++ len = 0; ++ do { ++ len++; ++ wb_mask >>= 8; ++ } while (wb_mask & 0xff); ++ ret = pci_write_block(pci_dev, address + index, ++ (uint8_t *)&val + index, len); + + if (!ret) + PT_LOG("Error: pci_write_block failed. return value[%d].\n", ret); +--- a/hw/pass-through.h ++++ b/hw/pass-through.h +@@ -372,8 +372,6 @@ struct pt_reg_info_tbl { + uint32_t ro_mask; + /* reg emulate field mask (ON:emu, OFF:passthrough) */ + uint32_t emu_mask; +- /* no write back allowed */ +- uint32_t no_wb; + /* emul reg initialize method */ + conf_reg_init init; + union { Added: head/sysutils/xen-tools/files/xsa128-qemuu.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa128-qemuu.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,118 @@ +xen: properly gate host writes of modified PCI CFG contents + +The old logic didn't work as intended when an access spanned multiple +fields (for example a 32-bit access to the location of the MSI Message +Data field with the high 16 bits not being covered by any known field). +Remove it and derive which fields not to write to from the accessed +fields' emulation masks: When they're all ones, there's no point in +doing any host write. + +This fixes a secondary issue at once: We obviously shouldn't make any +host write attempt when already the host read failed. + +This is XSA-128. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini + +--- a/hw/xen/xen_pt.c ++++ b/hw/xen/xen_pt.c +@@ -234,7 +234,7 @@ static void xen_pt_pci_write_config(PCID + int index = 0; + XenPTRegGroup *reg_grp_entry = NULL; + int rc = 0; +- uint32_t read_val = 0; ++ uint32_t read_val = 0, wb_mask; + int emul_len = 0; + XenPTReg *reg_entry = NULL; + uint32_t find_addr = addr; +@@ -271,6 +271,9 @@ static void xen_pt_pci_write_config(PCID + if (rc < 0) { + XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc); + memset(&read_val, 0xff, len); ++ wb_mask = 0; ++ } else { ++ wb_mask = 0xFFFFFFFF >> ((4 - len) << 3); + } + + /* pass directly to the real device for passthrough type register group */ +@@ -298,6 +301,11 @@ static void xen_pt_pci_write_config(PCID + + valid_mask <<= (find_addr - real_offset) << 3; + ptr_val = (uint8_t *)&val + (real_offset & 3); ++ if (reg->emu_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { ++ wb_mask &= ~((reg->emu_mask ++ >> ((find_addr - real_offset) << 3)) ++ << ((len - emul_len) << 3)); ++ } + + /* do emulation based on register size */ + switch (reg->size) { +@@ -350,10 +358,19 @@ static void xen_pt_pci_write_config(PCID + memory_region_transaction_commit(); + + out: +- if (!(reg && reg->no_wb)) { ++ for (index = 0; wb_mask; index += len) { + /* unknown regs are passed through */ +- rc = xen_host_pci_set_block(&s->real_device, addr, +- (uint8_t *)&val, len); ++ while (!(wb_mask & 0xff)) { ++ index++; ++ wb_mask >>= 8; ++ } ++ len = 0; ++ do { ++ len++; ++ wb_mask >>= 8; ++ } while (wb_mask & 0xff); ++ rc = xen_host_pci_set_block(&s->real_device, addr + index, ++ (uint8_t *)&val + index, len); + + if (rc < 0) { + XEN_PT_ERR(d, "pci_write_block failed. return value: %d.\n", rc); +--- a/hw/xen/xen_pt.h ++++ b/hw/xen/xen_pt.h +@@ -105,8 +105,6 @@ struct XenPTRegInfo { + uint32_t ro_mask; + /* reg emulate field mask (ON:emu, OFF:passthrough) */ + uint32_t emu_mask; +- /* no write back allowed */ +- uint32_t no_wb; + xen_pt_conf_reg_init init; + /* read/write function pointer + * for double_word/word/byte size */ +--- a/hw/xen/xen_pt_config_init.c ++++ b/hw/xen/xen_pt_config_init.c +@@ -1281,7 +1281,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] + .init_val = 0x00000000, + .ro_mask = 0x00000003, + .emu_mask = 0xFFFFFFFF, +- .no_wb = 1, + .init = xen_pt_common_reg_init, + .u.dw.read = xen_pt_long_reg_read, + .u.dw.write = xen_pt_msgaddr32_reg_write, +@@ -1293,7 +1292,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] + .init_val = 0x00000000, + .ro_mask = 0x00000000, + .emu_mask = 0xFFFFFFFF, +- .no_wb = 1, + .init = xen_pt_msgaddr64_reg_init, + .u.dw.read = xen_pt_long_reg_read, + .u.dw.write = xen_pt_msgaddr64_reg_write, +@@ -1305,7 +1303,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] + .init_val = 0x0000, + .ro_mask = 0x0000, + .emu_mask = 0xFFFF, +- .no_wb = 1, + .init = xen_pt_msgdata_reg_init, + .u.w.read = xen_pt_word_reg_read, + .u.w.write = xen_pt_msgdata_reg_write, +@@ -1317,7 +1314,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] + .init_val = 0x0000, + .ro_mask = 0x0000, + .emu_mask = 0xFFFF, +- .no_wb = 1, + .init = xen_pt_msgdata_reg_init, + .u.w.read = xen_pt_word_reg_read, + .u.w.write = xen_pt_msgdata_reg_write, Added: head/sysutils/xen-tools/files/xsa129-qemut.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa129-qemut.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,142 @@ +xen: don't allow guest to control MSI mask register + +It's being used by the hypervisor. For now simply mimic a device not +capable of masking, and fully emulate any accesses a guest may issue +nevertheless as simple reads/writes without side effects. + +This is XSA-129. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini + +--- a/hw/pass-through.c ++++ b/hw/pass-through.c +@@ -147,6 +147,10 @@ static uint32_t pt_msgaddr64_reg_init(st + struct pt_reg_info_tbl *reg, uint32_t real_offset); + static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset); ++static uint32_t pt_mask_reg_init(struct pt_dev *ptdev, ++ struct pt_reg_info_tbl *reg, uint32_t real_offset); ++static uint32_t pt_pending_reg_init(struct pt_dev *ptdev, ++ struct pt_reg_info_tbl *reg, uint32_t real_offset); + static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset); + static uint32_t pt_header_type_reg_init(struct pt_dev *ptdev, +@@ -644,7 +648,7 @@ static struct pt_reg_info_tbl pt_emu_reg + .size = 2, + .init_val = 0x0000, + .ro_mask = 0xFF8E, +- .emu_mask = 0x007F, ++ .emu_mask = 0x017F, + .init = pt_msgctrl_reg_init, + .u.w.read = pt_word_reg_read, + .u.w.write = pt_msgctrl_reg_write, +@@ -698,6 +702,50 @@ static struct pt_reg_info_tbl pt_emu_reg + .u.w.write = pt_msgdata_reg_write, + .u.w.restore = NULL, + }, ++ /* Mask reg (if PCI_MSI_FLAGS_MASK_BIT set, for 32-bit devices) */ ++ { ++ .offset = PCI_MSI_MASK_32, ++ .size = 4, ++ .init_val = 0x00000000, ++ .ro_mask = 0xFFFFFFFF, ++ .emu_mask = 0xFFFFFFFF, ++ .init = pt_mask_reg_init, ++ .u.dw.read = pt_long_reg_read, ++ .u.dw.write = pt_long_reg_write, ++ }, ++ /* Mask reg (if PCI_MSI_FLAGS_MASK_BIT set, for 64-bit devices) */ ++ { ++ .offset = PCI_MSI_MASK_64, ++ .size = 4, ++ .init_val = 0x00000000, ++ .ro_mask = 0xFFFFFFFF, ++ .emu_mask = 0xFFFFFFFF, ++ .init = pt_mask_reg_init, ++ .u.dw.read = pt_long_reg_read, ++ .u.dw.write = pt_long_reg_write, ++ }, ++ /* Pending reg (if PCI_MSI_FLAGS_MASK_BIT set, for 32-bit devices) */ ++ { ++ .offset = PCI_MSI_MASK_32 + 4, ++ .size = 4, ++ .init_val = 0x00000000, ++ .ro_mask = 0xFFFFFFFF, ++ .emu_mask = 0x00000000, ++ .init = pt_pending_reg_init, ++ .u.dw.read = pt_long_reg_read, ++ .u.dw.write = pt_long_reg_write, ++ }, ++ /* Pending reg (if PCI_MSI_FLAGS_MASK_BIT set, for 64-bit devices) */ ++ { ++ .offset = PCI_MSI_MASK_64 + 4, ++ .size = 4, ++ .init_val = 0x00000000, ++ .ro_mask = 0xFFFFFFFF, ++ .emu_mask = 0x00000000, ++ .init = pt_pending_reg_init, ++ .u.dw.read = pt_long_reg_read, ++ .u.dw.write = pt_long_reg_write, ++ }, + { + .size = 0, + }, +@@ -3023,6 +3071,42 @@ static uint32_t pt_msgdata_reg_init(stru + return PT_INVALID_REG; + } + ++/* this function will be called twice (for 32 bit and 64 bit type) */ ++/* initialize Mask register */ ++static uint32_t pt_mask_reg_init(struct pt_dev *ptdev, ++ struct pt_reg_info_tbl *reg, uint32_t real_offset) ++{ ++ uint32_t flags = ptdev->msi->flags; ++ uint32_t offset = reg->offset; ++ ++ if (!(flags & PCI_MSI_FLAGS_MASK_BIT)) ++ return PT_INVALID_REG; ++ ++ if (offset == (flags & PCI_MSI_FLAGS_64BIT ? ++ PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) ++ return reg->init_val; ++ ++ return PT_INVALID_REG; ++} ++ ++/* this function will be called twice (for 32 bit and 64 bit type) */ ++/* initialize Pending register */ ++static uint32_t pt_pending_reg_init(struct pt_dev *ptdev, ++ struct pt_reg_info_tbl *reg, uint32_t real_offset) ++{ ++ uint32_t flags = ptdev->msi->flags; ++ uint32_t offset = reg->offset; ++ ++ if (!(flags & PCI_MSI_FLAGS_MASK_BIT)) ++ return PT_INVALID_REG; ++ ++ if (offset == (flags & PCI_MSI_FLAGS_64BIT ? ++ PCI_MSI_MASK_64 + 4 : PCI_MSI_MASK_32 + 4)) ++ return reg->init_val; ++ ++ return PT_INVALID_REG; ++} ++ + /* initialize Message Control register for MSI-X */ + static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset) +--- a/hw/pass-through.h ++++ b/hw/pass-through.h +@@ -84,6 +84,12 @@ + #define PCI_MSI_FLAGS_MASK_BIT 0x0100 + #endif + ++#ifndef PCI_MSI_MASK_32 ++/* interrupt masking register */ ++#define PCI_MSI_MASK_32 12 ++#define PCI_MSI_MASK_64 16 ++#endif ++ + #ifndef PCI_EXP_TYPE_PCIE_BRIDGE + /* PCI/PCI-X to PCIE Bridge */ + #define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 Added: head/sysutils/xen-tools/files/xsa129-qemuu.patch ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sysutils/xen-tools/files/xsa129-qemuu.patch Thu Jun 11 18:26:45 2015 (r389243) @@ -0,0 +1,172 @@ +xen: don't allow guest to control MSI mask register + +It's being used by the hypervisor. For now simply mimic a device not +capable of masking, and fully emulate any accesses a guest may issue +nevertheless as simple reads/writes without side effects. + +This is XSA-129. + +Signed-off-by: Jan Beulich +Reviewed-by: Stefano Stabellini + +--- a/hw/pci/msi.c ++++ b/hw/pci/msi.c +@@ -21,10 +21,6 @@ + #include "hw/pci/msi.h" + #include "qemu/range.h" + +-/* Eventually those constants should go to Linux pci_regs.h */ +-#define PCI_MSI_PENDING_32 0x10 +-#define PCI_MSI_PENDING_64 0x14 +- + /* PCI_MSI_ADDRESS_LO */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***