FreeBSD Bugzilla – Attachment 159897 Details for
Bug 201931
sysutils/xen-tools: multiple vulnerabilities (CVE-2015-5154, CVE-2015-5166, CVE-2015-5165)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
sysutils/xen-tools: Update to 4.5.1 and apply XSA-139/XSA-140 patches
xen-tools-4.5.1.patch (text/plain), 154.35 KB, created by
Jason Unovitch
on 2015-08-15 12:42:12 UTC
(
hide
)
Description:
sysutils/xen-tools: Update to 4.5.1 and apply XSA-139/XSA-140 patches
Filename:
MIME Type:
Creator:
Jason Unovitch
Created:
2015-08-15 12:42:12 UTC
Size:
154.35 KB
patch
obsolete
>Index: Makefile >=================================================================== >--- Makefile (revision 394239) >+++ Makefile (working copy) >@@ -1,12 +1,11 @@ > # $FreeBSD$ > > PORTNAME= xen >-PKGNAMESUFFIX= -tools >-PORTVERSION= 4.5.0 >-PORTREVISION= 9 >+PORTVERSION= 4.5.1 > CATEGORIES= sysutils emulators > MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/ \ > http://code.coreboot.org/p/seabios/downloads/get/:seabios >+PKGNAMESUFFIX= -tools > > MAINTAINER= bapt@FreeBSD.org > COMMENT= Xen management tool, based on LibXenlight >@@ -14,13 +13,13 @@ > LICENSE= GPLv2 LGPL3 > LICENSE_COMB= multi > >-OPTIONS_DEFINE= DOCS >- > LIB_DEPENDS= libyajl.so:${PORTSDIR}/devel/yajl \ > liblzo2.so:${PORTSDIR}/archivers/lzo2 \ > libpixman-1.so:${PORTSDIR}/x11/pixman > BUILD_DEPENDS= dev86>0:${PORTSDIR}/devel/dev86 > >+OPTIONS_DEFINE= DOCS >+ > ONLY_FOR_ARCHS= amd64 > ONLY_FOR_ARCHS_REASON= "not yet ported to anything other than amd64" > >@@ -30,8 +29,9 @@ > > WRKSRC= ${WRKDIR}/xen-${PORTVERSION} > >-USES= cpe gmake perl5 python shebangfix libtool pkgconfig >+USES= cpe gmake libtool perl5 pkgconfig python shebangfix > USE_GNOME= glib20 >+USE_LDCONFIG= yes > GNU_CONFIGURE= yes > CONFIGURE_ENV= HOSTCC="${CC}" CC="${CC}" \ > ac_cv_path_BASH=${TRUE} \ >@@ -47,10 +47,7 @@ > --disable-curl \ > --cxx=c++ > >-EXTRA_PATCHES= ${FILESDIR}/xsa119-unstable.patch:-p1 \ >- ${FILESDIR}/xsa125.patch:-p1 \ >- ${FILESDIR}/xsa137.patch:-p1 \ >- ${FILESDIR}/0001-libelf-fix-elf_parse_bsdsyms-call.patch:-p1 \ >+EXTRA_PATCHES= ${FILESDIR}/xsa137.patch:-p1 \ > ${FILESDIR}/0002-libxc-fix-xc_dom_load_elf_symtab.patch:-p1 > > CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}" >@@ -63,7 +60,7 @@ > .include <bsd.port.options.mk> > > .if ${OPSYS} != FreeBSD >-IGNORE= Only supported on FreeBSD >+IGNORE= only supported on FreeBSD > .endif > > post-extract: >@@ -80,11 +77,11 @@ > ${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 ; \ >+ ${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 ; \ >+ ${PATCH} -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \ > done > > post-install: >Index: distinfo >=================================================================== >--- distinfo (revision 394239) >+++ distinfo (working copy) >@@ -1,4 +1,4 @@ >-SHA256 (xen-4.5.0.tar.gz) = 5bdb40e2b28d2eeb541bd71a9777f40cbe2ae444b987521d33f099541a006f3b >-SIZE (xen-4.5.0.tar.gz) = 18404933 >+SHA256 (xen-4.5.1.tar.gz) = 668c11d4fca67ac44329e369f810356eacd37b28d28fb96e66aac77f3c5e1371 >+SIZE (xen-4.5.1.tar.gz) = 18410400 > SHA256 (seabios-1.8.1.tar.gz) = 283bd848f5ce9d4bc52add973a856347e02c9ce89a9e6bc92c99359b87c9871d > SIZE (seabios-1.8.1.tar.gz) = 537712 >Index: files/0001-libelf-fix-elf_parse_bsdsyms-call.patch >=================================================================== >--- files/0001-libelf-fix-elf_parse_bsdsyms-call.patch (revision 394239) >+++ files/0001-libelf-fix-elf_parse_bsdsyms-call.patch (working copy) >@@ -1,36 +0,0 @@ >-From c2da83662498a5cd66512c684a0af178228f9d5a Mon Sep 17 00:00:00 2001 >-From: Roger Pau Monne <roger.pau@citrix.com> >-Date: Thu, 11 Jun 2015 17:08:26 +0200 >-Subject: [PATCH 1/2] libelf: fix elf_parse_bsdsyms call >-MIME-Version: 1.0 >-Content-Type: text/plain; charset=UTF-8 >-Content-Transfer-Encoding: 8bit >- >-elf_parse_bsdsyms expects the second paramater to be a physical address, not >-a virtual one. >- >-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> >-Cc: Ian Campbell <ian.campbell@citrix.com> >-Cc: Ian Jackson <ian.jackson@eu.citrix.com> >-Cc: Jan Beulich <jbeulich@suse.com> >-Cc: Tim Deegan <tim@xen.org> >---- >- xen/common/libelf/libelf-dominfo.c | 2 +- >- 1 file changed, 1 insertion(+), 1 deletion(-) >- >-diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c >-index 6120dd4..86403b9 100644 >---- a/xen/common/libelf/libelf-dominfo.c >-+++ b/xen/common/libelf/libelf-dominfo.c >-@@ -438,7 +438,7 @@ static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf, >- >- if ( parms->bsd_symtab ) >- { >-- elf_parse_bsdsyms(elf, parms->virt_kend); >-+ elf_parse_bsdsyms(elf, elf->pend); >- if ( elf->bsd_symtab_pend ) >- parms->virt_kend = elf->bsd_symtab_pend + parms->virt_offset; >- } >--- >-1.9.5 (Apple Git-50.3) >- >Index: files/xsa119-unstable.patch >=================================================================== >--- files/xsa119-unstable.patch (revision 394239) >+++ files/xsa119-unstable.patch (working copy) >@@ -1,99 +0,0 @@ >-From f433bfafbaf7d8a41c4c27aa3e8e78b1ab900b69 Mon Sep 17 00:00:00 2001 >-From: Ian Campbell <ian.campbell@citrix.com> >-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 <linux@eikelenboom.it> >-Signed-off-by: Ian Campbell <ian.campbell@citrix.com> >-Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> >---- >- 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 >- >Index: files/xsa125.patch >=================================================================== >--- files/xsa125.patch (revision 394239) >+++ files/xsa125.patch (working copy) >@@ -1,154 +0,0 @@ >-From 98670acc98cad5aee0e0714694a64d3b96675c36 Mon Sep 17 00:00:00 2001 >-From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> >-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 <jbeulich@suse.com> >-Acked-by: Jan Beulich <jbeulich@suse.com> >-Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> >-Acked-by: Ian Campbell <ian.campbell@citrix.com> >---- >-[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 >- >Index: files/xsa126-qemut.patch >=================================================================== >--- files/xsa126-qemut.patch (revision 394239) >+++ files/xsa126-qemut.patch (working copy) >@@ -1,151 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Acked-by: Ian Campbell <ian.campbell@citrix.com> >- >---- 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"); >Index: files/xsa126-qemuu.patch >=================================================================== >--- files/xsa126-qemuu.patch (revision 394239) >+++ files/xsa126-qemuu.patch (working copy) >@@ -1,128 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Acked-by: Ian Campbell <ian.campbell@citrix.com> >- >---- 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 */ >Index: files/xsa128-qemut.patch >=================================================================== >--- files/xsa128-qemut.patch (revision 394239) >+++ files/xsa128-qemut.patch (working copy) >@@ -1,125 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- 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 { >Index: files/xsa128-qemuu.patch >=================================================================== >--- files/xsa128-qemuu.patch (revision 394239) >+++ files/xsa128-qemuu.patch (working copy) >@@ -1,118 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- 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, >Index: files/xsa129-qemut.patch >=================================================================== >--- files/xsa129-qemut.patch (revision 394239) >+++ files/xsa129-qemut.patch (working copy) >@@ -1,142 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- 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 >Index: files/xsa129-qemuu.patch >=================================================================== >--- files/xsa129-qemuu.patch (revision 394239) >+++ files/xsa129-qemuu.patch (working copy) >@@ -1,172 +0,0 @@ >-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 <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- 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 */ >- #define PCI_MSI_ADDRESS_LO_MASK (~0x3) >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -1018,13 +1018,9 @@ static XenPTRegInfo xen_pt_emu_reg_pm[] >- */ >- >- /* Helper */ >--static bool xen_pt_msgdata_check_type(uint32_t offset, uint16_t flags) >--{ >-- /* check the offset whether matches the type or not */ >-- bool is_32 = (offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT); >-- bool is_64 = (offset == PCI_MSI_DATA_64) && (flags & PCI_MSI_FLAGS_64BIT); >-- return is_32 || is_64; >--} >-+#define xen_pt_msi_check_type(offset, flags, what) \ >-+ ((offset) == ((flags) & PCI_MSI_FLAGS_64BIT ? \ >-+ PCI_MSI_##what##_64 : PCI_MSI_##what##_32)) >- >- /* Message Control register */ >- static int xen_pt_msgctrl_reg_init(XenPCIPassthroughState *s, >-@@ -1136,7 +1132,45 @@ static int xen_pt_msgdata_reg_init(XenPC >- uint32_t offset = reg->offset; >- >- /* check the offset whether matches the type or not */ >-- if (xen_pt_msgdata_check_type(offset, flags)) { >-+ if (xen_pt_msi_check_type(offset, flags, DATA)) { >-+ *data = reg->init_val; >-+ } else { >-+ *data = XEN_PT_INVALID_REG; >-+ } >-+ return 0; >-+} >-+ >-+/* this function will be called twice (for 32 bit and 64 bit type) */ >-+/* initialize Mask register */ >-+static int xen_pt_mask_reg_init(XenPCIPassthroughState *s, >-+ XenPTRegInfo *reg, uint32_t real_offset, >-+ uint32_t *data) >-+{ >-+ uint32_t flags = s->msi->flags; >-+ >-+ /* check the offset whether matches the type or not */ >-+ if (!(flags & PCI_MSI_FLAGS_MASKBIT)) { >-+ *data = XEN_PT_INVALID_REG; >-+ } else if (xen_pt_msi_check_type(reg->offset, flags, MASK)) { >-+ *data = reg->init_val; >-+ } else { >-+ *data = XEN_PT_INVALID_REG; >-+ } >-+ return 0; >-+} >-+ >-+/* this function will be called twice (for 32 bit and 64 bit type) */ >-+/* initialize Pending register */ >-+static int xen_pt_pending_reg_init(XenPCIPassthroughState *s, >-+ XenPTRegInfo *reg, uint32_t real_offset, >-+ uint32_t *data) >-+{ >-+ uint32_t flags = s->msi->flags; >-+ >-+ /* check the offset whether matches the type or not */ >-+ if (!(flags & PCI_MSI_FLAGS_MASKBIT)) { >-+ *data = XEN_PT_INVALID_REG; >-+ } else if (xen_pt_msi_check_type(reg->offset, flags, PENDING)) { >- *data = reg->init_val; >- } else { >- *data = XEN_PT_INVALID_REG; >-@@ -1224,7 +1258,7 @@ static int xen_pt_msgdata_reg_write(XenP >- uint32_t offset = reg->offset; >- >- /* check the offset whether matches the type or not */ >-- if (!xen_pt_msgdata_check_type(offset, msi->flags)) { >-+ if (!xen_pt_msi_check_type(offset, msi->flags, DATA)) { >- /* exit I/O emulator */ >- XEN_PT_ERR(&s->dev, "the offset does not match the 32/64 bit type!\n"); >- return -1; >-@@ -1269,7 +1303,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] >- .size = 2, >- .init_val = 0x0000, >- .ro_mask = 0xFF8E, >-- .emu_mask = 0x007F, >-+ .emu_mask = 0x017F, >- .init = xen_pt_msgctrl_reg_init, >- .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_msgctrl_reg_write, >-@@ -1318,6 +1352,50 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] >- .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_msgdata_reg_write, >- }, >-+ /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */ >-+ { >-+ .offset = PCI_MSI_MASK_32, >-+ .size = 4, >-+ .init_val = 0x00000000, >-+ .ro_mask = 0xFFFFFFFF, >-+ .emu_mask = 0xFFFFFFFF, >-+ .init = xen_pt_mask_reg_init, >-+ .u.dw.read = xen_pt_long_reg_read, >-+ .u.dw.write = xen_pt_long_reg_write, >-+ }, >-+ /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */ >-+ { >-+ .offset = PCI_MSI_MASK_64, >-+ .size = 4, >-+ .init_val = 0x00000000, >-+ .ro_mask = 0xFFFFFFFF, >-+ .emu_mask = 0xFFFFFFFF, >-+ .init = xen_pt_mask_reg_init, >-+ .u.dw.read = xen_pt_long_reg_read, >-+ .u.dw.write = xen_pt_long_reg_write, >-+ }, >-+ /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */ >-+ { >-+ .offset = PCI_MSI_MASK_32 + 4, >-+ .size = 4, >-+ .init_val = 0x00000000, >-+ .ro_mask = 0xFFFFFFFF, >-+ .emu_mask = 0x00000000, >-+ .init = xen_pt_pending_reg_init, >-+ .u.dw.read = xen_pt_long_reg_read, >-+ .u.dw.write = xen_pt_long_reg_write, >-+ }, >-+ /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */ >-+ { >-+ .offset = PCI_MSI_MASK_64 + 4, >-+ .size = 4, >-+ .init_val = 0x00000000, >-+ .ro_mask = 0xFFFFFFFF, >-+ .emu_mask = 0x00000000, >-+ .init = xen_pt_pending_reg_init, >-+ .u.dw.read = xen_pt_long_reg_read, >-+ .u.dw.write = xen_pt_long_reg_write, >-+ }, >- { >- .size = 0, >- }, >---- a/include/hw/pci/pci_regs.h >-+++ b/include/hw/pci/pci_regs.h >-@@ -298,8 +298,10 @@ >- #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ >- #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ >- #define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */ >-+#define PCI_MSI_PENDING_32 16 /* Pending bits register for 32-bit devices */ >- #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ >- #define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */ >-+#define PCI_MSI_PENDING_64 20 /* Pending bits register for 32-bit devices */ >- >- /* MSI-X registers */ >- #define PCI_MSIX_FLAGS 2 >Index: files/xsa130-qemut.patch >=================================================================== >--- files/xsa130-qemut.patch (revision 394239) >+++ files/xsa130-qemut.patch (working copy) >@@ -1,21 +0,0 @@ >-xen/MSI-X: disable logging by default >- >-... to avoid allowing the guest to cause the control domain's disk to >-fill. >- >-This is XSA-130. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/pass-through.h >-+++ b/hw/pass-through.h >-@@ -27,7 +27,7 @@ >- #include "qemu-timer.h" >- >- /* Log acesss */ >--#define PT_LOGGING_ENABLED >-+/* #define PT_LOGGING_ENABLED */ >- >- /* Print errors even if logging is disabled */ >- #define PT_ERR(_f, _a...) fprintf(logfile, "%s: " _f, __func__, ##_a) >Index: files/xsa130-qemuu.patch >=================================================================== >--- files/xsa130-qemuu.patch (revision 394239) >+++ files/xsa130-qemuu.patch (working copy) >@@ -1,71 +0,0 @@ >-xen/MSI-X: limit error messages resulting from bad guest behavior >- >-... to avoid allowing the guest to cause the control domain's disk to >-fill. >- >-The first message in pci_msix_write() can simply be deleted, as this >-is indeed bad guest behavior, but such out of bounds writes don't >-really need to be logged. >- >-The second one is more problematic, as there guest behavior may only >-appear to be wrong: For one, the old logic didn't take the mask-all bit >-into account. And then this shouldn't depend on host device state (i.e. >-the host may have masked the entry without the guest having done so). >-Plus these writes shouldn't be dropped even when an entry is unmasked. >-Instead, if they can't be made take effect right away, they should take >-effect on the next unmasking or enabling operation - the specification >-explicitly describes such caching behavior. Until we can validly drop >-the message (implementing such caching/latching behavior), issue the >-message just once per MSI-X table entry. >- >-Note that the log message in pci_msix_read() similar to the one being >-removed here is not an issue: "addr" being of unsigned type, and the >-maximum size of the MSI-X table being 32k, entry_nr simply can't be >-negative and hence the conditonal guarding issuing of the message will >-never be true. >- >-This is XSA-130. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/xen/xen_pt.h >-+++ b/hw/xen/xen_pt.h >-@@ -175,6 +175,7 @@ typedef struct XenPTMSIXEntry { >- uint32_t data; >- uint32_t vector_ctrl; >- bool updated; /* indicate whether MSI ADDR or DATA is updated */ >-+ bool warned; /* avoid issuing (bogus) warning more than once */ >- } XenPTMSIXEntry; >- typedef struct XenPTMSIX { >- uint32_t ctrl_offset; >---- a/hw/xen/xen_pt_msi.c >-+++ b/hw/xen/xen_pt_msi.c >-@@ -434,11 +434,10 @@ static void pci_msix_write(void *opaque, >- XenPCIPassthroughState *s = opaque; >- XenPTMSIX *msix = s->msix; >- XenPTMSIXEntry *entry; >-- int entry_nr, offset; >-+ unsigned int entry_nr, offset; >- >- entry_nr = addr / PCI_MSIX_ENTRY_SIZE; >-- if (entry_nr < 0 || entry_nr >= msix->total_entries) { >-- XEN_PT_ERR(&s->dev, "asked MSI-X entry '%i' invalid!\n", entry_nr); >-+ if (entry_nr >= msix->total_entries) { >- return; >- } >- entry = &msix->msix_entry[entry_nr]; >-@@ -460,8 +459,11 @@ static void pci_msix_write(void *opaque, >- + PCI_MSIX_ENTRY_VECTOR_CTRL; >- >- if (msix->enabled && !(*vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { >-- XEN_PT_ERR(&s->dev, "Can't update msix entry %d since MSI-X is" >-- " already enabled.\n", entry_nr); >-+ if (!entry->warned) { >-+ entry->warned = true; >-+ XEN_PT_ERR(&s->dev, "Can't update msix entry %d since MSI-X is" >-+ " already enabled.\n", entry_nr); >-+ } >- return; >- } >- >Index: files/xsa131-qemut-1.patch >=================================================================== >--- files/xsa131-qemut-1.patch (revision 394239) >+++ files/xsa131-qemut-1.patch (working copy) >@@ -1,60 +0,0 @@ >-xen/MSI: don't open-code pass-through of enable bit modifications >- >-Without this the actual XSA-131 fix would cause the enable bit to not >-get set anymore (due to the write back getting suppressed there based >-on the OR of emu_mask, ro_mask, and res_mask). >- >-Note that the fiddling with the enable bit shouldn't really be done by >-qemu, but making this work right (via libxc and the hypervisor) will >-require more extensive changes, which can be postponed until after the >-security issue got addressed. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -648,7 +648,7 @@ static struct pt_reg_info_tbl pt_emu_reg >- .size = 2, >- .init_val = 0x0000, >- .ro_mask = 0xFF8E, >-- .emu_mask = 0x017F, >-+ .emu_mask = 0x017E, >- .init = pt_msgctrl_reg_init, >- .u.w.read = pt_word_reg_read, >- .u.w.write = pt_msgctrl_reg_write, >-@@ -3901,6 +3901,9 @@ static int pt_msgctrl_reg_write(struct p >- >- /* modify emulate register */ >- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; >-+ /* also emulate MSI_ENABLE bit for MSI-INTx translation */ >-+ if (ptdev->msi_trans_en) >-+ writable_mask |= PCI_MSI_FLAGS_ENABLE & valid_mask; >- cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); >- /* update the msi_info too */ >- ptdev->msi->flags |= cfg_entry->data & >-@@ -3909,6 +3912,9 @@ static int pt_msgctrl_reg_write(struct p >- /* create value for writing to I/O device register */ >- val = *value; >- throughable_mask = ~reg->emu_mask & valid_mask; >-+ /* don't pass through MSI_ENABLE bit for MSI-INTx translation */ >-+ if (ptdev->msi_trans_en) >-+ throughable_mask &= ~PCI_MSI_FLAGS_ENABLE; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- /* update MSI */ >-@@ -3952,12 +3958,6 @@ static int pt_msgctrl_reg_write(struct p >- } >- } >- >-- /* pass through MSI_ENABLE bit when no MSI-INTx translation */ >-- if (!ptdev->msi_trans_en) { >-- *value &= ~PCI_MSI_FLAGS_ENABLE; >-- *value |= val & PCI_MSI_FLAGS_ENABLE; >-- } >-- >- return 0; >- } >- >Index: files/xsa131-qemut-2.patch >=================================================================== >--- files/xsa131-qemut-2.patch (revision 394239) >+++ files/xsa131-qemut-2.patch (working copy) >@@ -1,140 +0,0 @@ >-xen/pt: consolidate PM capability emu_mask >- >-There's no point in xen_pt_pmcsr_reg_{read,write}() each ORing >-PCI_PM_CTRL_STATE_MASK and PCI_PM_CTRL_NO_SOFT_RESET into a local >-emu_mask variable - we can have the same effect by setting the field >-descriptor's emu_mask member suitably right away. Note that >-xen_pt_pmcsr_reg_write() is being retained in order to allow later >-patches to be less intrusive. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Acked-by: Ian Campbell <ian.campbell@citrix.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -179,9 +179,6 @@ static int pt_long_reg_read(struct pt_de >- static int pt_bar_reg_read(struct pt_dev *ptdev, >- struct pt_reg_tbl *cfg_entry, >- uint32_t *value, uint32_t valid_mask); >--static int pt_pmcsr_reg_read(struct pt_dev *ptdev, >-- struct pt_reg_tbl *cfg_entry, >-- uint16_t *value, uint16_t valid_mask); >- static int pt_byte_reg_write(struct pt_dev *ptdev, >- struct pt_reg_tbl *cfg_entry, >- uint8_t *value, uint8_t dev_value, uint8_t valid_mask); >-@@ -494,7 +491,7 @@ static struct pt_reg_info_tbl pt_emu_reg >- .u.w.write = pt_word_reg_write, >- .u.w.restore = NULL, >- }, >-- /* PCI Power Management Control/Status reg */ >-+ /* PCI Power Management Control/Status reg (->power_mgmt on) */ >- { >- .offset = PCI_PM_CTRL, >- .size = 2, >-@@ -502,7 +499,19 @@ static struct pt_reg_info_tbl pt_emu_reg >- .ro_mask = 0xE1FC, >- .emu_mask = 0x8100, >- .init = pt_pmcsr_reg_init, >-- .u.w.read = pt_pmcsr_reg_read, >-+ .u.w.read = pt_word_reg_read, >-+ .u.w.write = pt_pmcsr_reg_write, >-+ .u.w.restore = pt_pmcsr_reg_restore, >-+ }, >-+ /* PCI Power Management Control/Status reg (->power_mgmt off) */ >-+ { >-+ .offset = PCI_PM_CTRL, >-+ .size = 2, >-+ .init_val = 0x0008, >-+ .ro_mask = 0xE1FC, >-+ .emu_mask = 0x810B, >-+ .init = pt_pmcsr_reg_init, >-+ .u.w.read = pt_word_reg_read, >- .u.w.write = pt_pmcsr_reg_write, >- .u.w.restore = pt_pmcsr_reg_restore, >- }, >-@@ -2919,6 +2928,7 @@ static uint32_t pt_pmc_reg_init(struct p >- return reg->init_val; >- } >- >-+/* this function will be called twice (for ->power_mgmt on and off cases) */ >- /* initialize PCI Power Management Control/Status register */ >- static uint32_t pt_pmcsr_reg_init(struct pt_dev *ptdev, >- struct pt_reg_info_tbl *reg, uint32_t real_offset) >-@@ -2926,8 +2936,23 @@ static uint32_t pt_pmcsr_reg_init(struct >- PCIDevice *d = &ptdev->dev; >- uint16_t cap_ver = 0; >- >-- if (!ptdev->power_mgmt) >-- return reg->init_val; >-+ switch (reg->emu_mask & (PCI_PM_CTRL_STATE_MASK | >-+ PCI_PM_CTRL_NO_SOFT_RESET)) >-+ { >-+ case 0: >-+ if (!ptdev->power_mgmt) >-+ return PT_INVALID_REG; >-+ break; >-+ case PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_NO_SOFT_RESET: >-+ if (!ptdev->power_mgmt) >-+ return reg->init_val; >-+ return PT_INVALID_REG; >-+ default: >-+ /* exit I/O emulator */ >-+ PT_LOG("Internal error: Invalid PMCSR emulation mask %04x." >-+ " I/O emulator exit.\n", reg->emu_mask); >-+ exit(1); >-+ } >- >- /* check PCI Power Management support version */ >- cap_ver = ptdev->pm_state->pmc_field & PCI_PM_CAP_VER_MASK; >-@@ -3417,24 +3442,6 @@ static int pt_bar_reg_read(struct pt_dev >- } >- >- >--/* read Power Management Control/Status register */ >--static int pt_pmcsr_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 = reg->emu_mask; >-- >-- if (!ptdev->power_mgmt) >-- valid_emu_mask |= PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_NO_SOFT_RESET; >-- >-- valid_emu_mask = valid_emu_mask & valid_mask ; >-- *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); >-- >-- return 0; >--} >-- >-- >- /* write byte size emulate register */ >- static int pt_byte_reg_write(struct pt_dev *ptdev, >- struct pt_reg_tbl *cfg_entry, >-@@ -3768,21 +3775,17 @@ static int pt_pmcsr_reg_write(struct pt_ >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- PCIDevice *d = &ptdev->dev; >-- uint16_t emu_mask = reg->emu_mask; >- uint16_t writable_mask = 0; >- uint16_t throughable_mask = 0; >- struct pt_pm_info *pm_state = ptdev->pm_state; >- uint16_t read_val = 0; >- >-- if (!ptdev->power_mgmt) >-- emu_mask |= PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_NO_SOFT_RESET; >-- >- /* modify emulate register */ >-- writable_mask = emu_mask & ~reg->ro_mask & valid_mask; >-+ writable_mask = reg->emu_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; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- if (!ptdev->power_mgmt) >Index: files/xsa131-qemut-3.patch >=================================================================== >--- files/xsa131-qemut-3.patch (revision 394239) >+++ files/xsa131-qemut-3.patch (working copy) >@@ -1,22 +0,0 @@ >-xen/pt: correctly handle PM status bit >- >-xen_pt_pmcsr_reg_write() needs an adjustment to deal with the RW1C >-nature of the not passed through bit 15 (PCI_PM_CTRL_PME_STATUS). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -3786,7 +3786,8 @@ static int pt_pmcsr_reg_write(struct pt_ >- >- /* create value for writing to I/O device register */ >- throughable_mask = ~reg->emu_mask & valid_mask; >-- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >-+ *value = PT_MERGE_VALUE(*value, dev_value & ~PCI_PM_CTRL_PME_STATUS, >-+ throughable_mask); >- >- if (!ptdev->power_mgmt) >- return 0; >Index: files/xsa131-qemut-4.patch >=================================================================== >--- files/xsa131-qemut-4.patch (revision 394239) >+++ files/xsa131-qemut-4.patch (working copy) >@@ -1,266 +0,0 @@ >-xen/pt: split out calculation of throughable mask in PCI config space handling >- >-This is just to avoid having to adjust that calculation later in >-multiple places. >- >-Note that including ->ro_mask in get_throughable_mask()'s calculation >-is only an apparent (i.e. benign) behavioral change: For r/o fields it >-doesn't matter > whether they get passed through - either the same flag >-is also set in emu_mask (then there's no change at all) or the field is >-r/o in hardware (and hence a write won't change it anyway). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -3442,6 +3442,15 @@ static int pt_bar_reg_read(struct pt_dev >- } >- >- >-+static uint32_t get_throughable_mask(const struct pt_dev *ptdev, >-+ const struct pt_reg_info_tbl *reg, >-+ uint32_t valid_mask) >-+{ >-+ uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask); >-+ >-+ return throughable_mask & valid_mask; >-+} >-+ >- /* write byte size emulate register */ >- static int pt_byte_reg_write(struct pt_dev *ptdev, >- struct pt_reg_tbl *cfg_entry, >-@@ -3449,14 +3458,13 @@ static int pt_byte_reg_write(struct pt_d >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint8_t writable_mask = 0; >-- uint8_t throughable_mask = 0; >-+ uint8_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- return 0; >-@@ -3469,14 +3477,13 @@ static int pt_word_reg_write(struct pt_d >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- return 0; >-@@ -3489,14 +3496,13 @@ static int pt_long_reg_write(struct pt_d >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >-+ uint32_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- return 0; >-@@ -3509,7 +3515,7 @@ static int pt_cmd_reg_write(struct pt_de >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- uint16_t wr_value = *value; >- >- /* modify emulate register */ >-@@ -3517,8 +3523,6 @@ static int pt_cmd_reg_write(struct pt_de >- cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- >- if (*value & PCI_COMMAND_DISABLE_INTx) >- { >- if (ptdev->msi_trans_en) >-@@ -3564,7 +3568,6 @@ static int pt_bar_reg_write(struct pt_de >- PCIDevice *d = (PCIDevice *)&ptdev->dev; >- PCIIORegion *r; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t bar_emu_mask = 0; >- uint32_t bar_ro_mask = 0; >- uint32_t new_addr, last_addr; >-@@ -3691,8 +3694,7 @@ static int pt_bar_reg_write(struct pt_de >- >- exit: >- /* create value for writing to I/O device register */ >-- throughable_mask = ~bar_emu_mask & valid_mask; >-- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >-+ *value = PT_MERGE_VALUE(*value, dev_value, 0); >- >- /* After BAR reg update, we need to remap BAR*/ >- reg_grp_entry = pt_find_reg_grp(ptdev, PCI_COMMAND); >-@@ -3719,9 +3721,8 @@ static int pt_exp_rom_bar_reg_write(stru >- PCIDevice *d = (PCIDevice *)&ptdev->dev; >- PCIIORegion *r; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >-+ uint32_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- uint32_t r_size = 0; >-- uint32_t bar_emu_mask = 0; >- uint32_t bar_ro_mask = 0; >- >- r = &d->io_regions[PCI_ROM_SLOT]; >-@@ -3731,7 +3732,6 @@ static int pt_exp_rom_bar_reg_write(stru >- PT_GET_EMUL_SIZE(base->bar_flag, r_size); >- >- /* set emulate mask and read-only mask */ >-- bar_emu_mask = reg->emu_mask; >- bar_ro_mask = (reg->ro_mask | (r_size - 1)) & ~PCI_ROM_ADDRESS_ENABLE; >- >- /* modify emulate register */ >-@@ -3751,7 +3751,6 @@ static int pt_exp_rom_bar_reg_write(stru >- r->addr = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~bar_emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- /* After BAR reg update, we need to remap BAR*/ >-@@ -3776,7 +3775,7 @@ static int pt_pmcsr_reg_write(struct pt_ >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- PCIDevice *d = &ptdev->dev; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- struct pt_pm_info *pm_state = ptdev->pm_state; >- uint16_t read_val = 0; >- >-@@ -3785,7 +3784,6 @@ static int pt_pmcsr_reg_write(struct pt_ >- cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value & ~PCI_PM_CTRL_PME_STATUS, >- throughable_mask); >- >-@@ -3894,7 +3892,7 @@ static int pt_msgctrl_reg_write(struct p >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- uint16_t old_ctrl = cfg_entry->data; >- PCIDevice *pd = (PCIDevice *)ptdev; >- uint16_t val; >-@@ -3906,8 +3904,10 @@ static int pt_msgctrl_reg_write(struct p >- /* modify emulate register */ >- writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; >- /* also emulate MSI_ENABLE bit for MSI-INTx translation */ >-- if (ptdev->msi_trans_en) >-+ if (ptdev->msi_trans_en) { >- writable_mask |= PCI_MSI_FLAGS_ENABLE & valid_mask; >-+ throughable_mask &= ~PCI_MSI_FLAGS_ENABLE; >-+ } >- cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); >- /* update the msi_info too */ >- ptdev->msi->flags |= cfg_entry->data & >-@@ -3915,10 +3915,6 @@ static int pt_msgctrl_reg_write(struct p >- >- /* create value for writing to I/O device register */ >- val = *value; >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- /* don't pass through MSI_ENABLE bit for MSI-INTx translation */ >-- if (ptdev->msi_trans_en) >-- throughable_mask &= ~PCI_MSI_FLAGS_ENABLE; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- /* update MSI */ >-@@ -3972,7 +3968,6 @@ static int pt_msgaddr32_reg_write(struct >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t old_addr = cfg_entry->data; >- >- /* modify emulate register */ >-@@ -3982,8 +3977,7 @@ static int pt_msgaddr32_reg_write(struct >- ptdev->msi->addr_lo = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >-+ *value = PT_MERGE_VALUE(*value, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_addr) >-@@ -4002,7 +3996,6 @@ static int pt_msgaddr64_reg_write(struct >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t old_addr = cfg_entry->data; >- >- /* check whether the type is 64 bit or not */ >-@@ -4020,8 +4013,7 @@ static int pt_msgaddr64_reg_write(struct >- ptdev->msi->addr_hi = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >-+ *value = PT_MERGE_VALUE(*value, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_addr) >-@@ -4041,7 +4033,6 @@ static int pt_msgdata_reg_write(struct p >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >- uint16_t old_data = cfg_entry->data; >- uint32_t flags = ptdev->msi->flags; >- uint32_t offset = reg->offset; >-@@ -4062,8 +4053,7 @@ static int pt_msgdata_reg_write(struct p >- ptdev->msi->data = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >-+ *value = PT_MERGE_VALUE(*value, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_data) >-@@ -4082,7 +4072,7 @@ static int pt_msixctrl_reg_write(struct >- { >- struct pt_reg_info_tbl *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(ptdev, reg, valid_mask); >- uint16_t old_ctrl = cfg_entry->data; >- >- /* modify emulate register */ >-@@ -4090,7 +4080,6 @@ static int pt_msixctrl_reg_write(struct >- cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >- *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); >- >- /* update MSI-X */ >Index: files/xsa131-qemut-5.patch >=================================================================== >--- files/xsa131-qemut-5.patch (revision 394239) >+++ files/xsa131-qemut-5.patch (working copy) >@@ -1,22 +0,0 @@ >-xen/pt: mark all PCIe capability bits read-only >- >-xen_pt_emu_reg_pcie[]'s PCI_EXP_DEVCAP needs to cover all bits as read- >-only to avoid unintended write-back (just a precaution, the field ought >-to be read-only in hardware). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -577,7 +577,7 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_EXP_DEVCAP, >- .size = 4, >- .init_val = 0x00000000, >-- .ro_mask = 0x1FFCFFFF, >-+ .ro_mask = 0xFFFFFFFF, >- .emu_mask = 0x10000000, >- .init = pt_common_reg_init, >- .u.dw.read = pt_long_reg_read, >Index: files/xsa131-qemut-6.patch >=================================================================== >--- files/xsa131-qemut-6.patch (revision 394239) >+++ files/xsa131-qemut-6.patch (working copy) >@@ -1,85 +0,0 @@ >-xen/pt: mark reserved bits in PCI config space fields >- >-The adjustments are solely to make the subsequent patches work right >-(and hence make the patch set consistent), namely if permissive mode >-(introduced by the last patch) gets used (as both reserved registers >-and reserved fields must be similarly protected from guest access in >-default mode, but the guest should be allowed access to them in >-permissive mode). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -283,7 +283,7 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_COMMAND, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0xF880, >-+ .res_mask = 0xF880, >- .emu_mask = 0x0743, >- .init = pt_common_reg_init, >- .u.w.read = pt_word_reg_read, >-@@ -310,7 +310,8 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_STATUS, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0x06FF, >-+ .res_mask = 0x0007, >-+ .ro_mask = 0x06F8, >- .emu_mask = 0x0010, >- .init = pt_status_reg_init, >- .u.w.read = pt_word_reg_read, >-@@ -496,7 +497,8 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_PM_CTRL, >- .size = 2, >- .init_val = 0x0008, >-- .ro_mask = 0xE1FC, >-+ .res_mask = 0x00F0, >-+ .ro_mask = 0xE10C, >- .emu_mask = 0x8100, >- .init = pt_pmcsr_reg_init, >- .u.w.read = pt_word_reg_read, >-@@ -508,7 +510,8 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_PM_CTRL, >- .size = 2, >- .init_val = 0x0008, >-- .ro_mask = 0xE1FC, >-+ .res_mask = 0x00F0, >-+ .ro_mask = 0xE10C, >- .emu_mask = 0x810B, >- .init = pt_pmcsr_reg_init, >- .u.w.read = pt_word_reg_read, >-@@ -656,7 +659,8 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_MSI_FLAGS, // 2 >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0xFF8E, >-+ .res_mask = 0xFE00, >-+ .ro_mask = 0x018E, >- .emu_mask = 0x017E, >- .init = pt_msgctrl_reg_init, >- .u.w.read = pt_word_reg_read, >-@@ -779,7 +783,8 @@ static struct pt_reg_info_tbl pt_emu_reg >- .offset = PCI_MSI_FLAGS, // 2 >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0x3FFF, >-+ .res_mask = 0x3800, >-+ .ro_mask = 0x07FF, >- .emu_mask = 0x0000, >- .init = pt_msixctrl_reg_init, >- .u.w.read = pt_word_reg_read, >---- a/hw/pass-through.h >-+++ b/hw/pass-through.h >-@@ -376,6 +376,8 @@ struct pt_reg_info_tbl { >- uint32_t size; >- /* reg initial value */ >- uint32_t init_val; >-+ /* reg reserved field mask (ON:reserved, OFF:defined) */ >-+ uint32_t res_mask; >- /* reg read only field mask (ON:RO/ROS, OFF:other) */ >- uint32_t ro_mask; >- /* reg emulate field mask (ON:emu, OFF:passthrough) */ >Index: files/xsa131-qemut-7.patch >=================================================================== >--- files/xsa131-qemut-7.patch (revision 394239) >+++ files/xsa131-qemut-7.patch (working copy) >@@ -1,81 +0,0 @@ >-xen/pt: add a few PCI config space field descriptions >- >-Since the next patch will turn all not explicitly described fields >-read-only by default, those fields that have guest writable bits need >-to be given explicit descriptors. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -538,6 +538,16 @@ static struct pt_reg_info_tbl pt_emu_reg >- .u.b.restore = NULL, >- }, >- { >-+ .offset = PCI_VPD_ADDR, >-+ .size = 2, >-+ .ro_mask = 0x0003, >-+ .emu_mask = 0x0003, >-+ .init = pt_common_reg_init, >-+ .u.w.read = pt_word_reg_read, >-+ .u.w.write = pt_word_reg_write, >-+ .u.w.restore = pt_word_reg_restore, >-+ }, >-+ { >- .size = 0, >- }, >- }; >-@@ -599,6 +609,17 @@ static struct pt_reg_info_tbl pt_emu_reg >- .u.w.write = pt_word_reg_write, >- .u.w.restore = pt_word_reg_restore, >- }, >-+ /* Device Status reg */ >-+ { >-+ .offset = PCI_EXP_DEVSTA, >-+ .size = 2, >-+ .res_mask = 0xFFC0, >-+ .ro_mask = 0x0030, >-+ .init = pt_common_reg_init, >-+ .u.w.read = pt_word_reg_read, >-+ .u.w.write = pt_word_reg_write, >-+ .u.w.restore = pt_word_reg_restore, >-+ }, >- /* Link Control reg */ >- { >- .offset = PCI_EXP_LNKCTL, >-@@ -611,6 +632,16 @@ static struct pt_reg_info_tbl pt_emu_reg >- .u.w.write = pt_word_reg_write, >- .u.w.restore = pt_word_reg_restore, >- }, >-+ /* Link Status reg */ >-+ { >-+ .offset = PCI_EXP_LNKSTA, >-+ .size = 2, >-+ .ro_mask = 0x3FFF, >-+ .init = pt_common_reg_init, >-+ .u.w.read = pt_word_reg_read, >-+ .u.w.write = pt_word_reg_write, >-+ .u.w.restore = pt_word_reg_restore, >-+ }, >- /* Device Control 2 reg */ >- { >- .offset = 0x28, >---- a/hw/pass-through.h >-+++ b/hw/pass-through.h >-@@ -105,6 +105,14 @@ >- #define PCI_EXP_TYPE_ROOT_EC 0xa >- #endif >- >-+#ifndef PCI_VPD_ADDR >-+/* Vital Product Data */ >-+#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */ >-+#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ >-+#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ >-+#define PCI_VPD_DATA 4 /* 32-bits of data returned here */ >-+#endif >-+ >- #ifndef PCI_ERR_UNCOR_MASK >- /* Uncorrectable Error Mask */ >- #define PCI_ERR_UNCOR_MASK 8 >Index: files/xsa131-qemut-8.patch >=================================================================== >--- files/xsa131-qemut-8.patch (revision 394239) >+++ files/xsa131-qemut-8.patch (working copy) >@@ -1,139 +0,0 @@ >-xen/pt: unknown PCI config space fields should be read-only >- >-... by default. Add a per-device "permissive" mode similar to pciback's >-to allow restoring previous behavior (and hence break security again, >-i.e. should be used only for trusted guests). >- >-This is part of XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>) >- >---- a/hw/pass-through.c >-+++ b/hw/pass-through.c >-@@ -1613,10 +1613,10 @@ 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, wb_mask; >-+ uint32_t read_val = 0, wb_mask, wp_mask; >- uint8_t *ptr_val = NULL; >- int emul_len = 0; >-- int index = 0; >-+ int index = 0, wp_flag = 0; >- int ret = 0; >- >- #ifdef PT_DEBUG_PCI_CONFIG_ACCESS >-@@ -1695,7 +1695,14 @@ static void pt_pci_write_config(PCIDevic >- >- /* pass directly to libpci for passthrough type register group */ >- if (reg_grp_entry == NULL) >-+ { >-+ if (!assigned_device->permissive) >-+ { >-+ wb_mask = 0; >-+ wp_flag = 1; >-+ } >- goto out; >-+ } >- >- /* adjust the read and write value to appropriate CFC-CFF window */ >- read_val <<= ((address & 3) << 3); >-@@ -1714,11 +1721,12 @@ 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)) >-+ wp_mask = reg->emu_mask | reg->ro_mask; >-+ if (!assigned_device->permissive) >-+ wp_mask |= reg->res_mask; >-+ if (wp_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) >-+ wb_mask &= ~((wp_mask >> ((find_addr - real_offset) << 3)) >- << ((len - emul_len) << 3)); >-- } >- >- /* do emulation depend on register size */ >- switch (reg->size) { >-@@ -1767,6 +1775,16 @@ static void pt_pci_write_config(PCIDevic >- /* nothing to do with passthrough type register, >- * continue to find next byte >- */ >-+ if (!assigned_device->permissive) >-+ { >-+ wb_mask &= ~(0xff << ((len - emul_len) << 3)); >-+ /* Unused BARs will make it here, but we don't want to issue >-+ * warnings for writes to them (bogus writes get dealt with >-+ * above). >-+ */ >-+ if (index < 0) >-+ wp_flag = 1; >-+ } >- emul_len--; >- find_addr++; >- } >-@@ -1776,6 +1794,15 @@ static void pt_pci_write_config(PCIDevic >- val >>= ((address & 3) << 3); >- >- out: >-+ if (wp_flag && !assigned_device->permissive_warned) >-+ { >-+ assigned_device->permissive_warned = 1; >-+ PT_LOG("Write-back to unknown field 0x%02x (partially) inhibited (0x%0*x)\n", >-+ addr, len * 2, wb_mask); >-+ PT_LOG("If device %02x:%02x.%o doesn't work, try enabling permissive\n", >-+ pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); >-+ PT_LOG("mode (unsafe) and if it helps report the problem to xen-devel\n"); >-+ } >- for (index = 0; wb_mask; index += len) { >- /* unknown regs are passed through */ >- while (!(wb_mask & 0xff)) { >-@@ -3484,6 +3511,9 @@ static uint32_t get_throughable_mask(con >- { >- uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask); >- >-+ if (!ptdev->permissive) >-+ throughable_mask &= ~reg->res_mask; >-+ >- return throughable_mask & valid_mask; >- } >- >-@@ -4322,7 +4352,7 @@ static struct pt_dev * register_real_dev >- uint8_t e_device, e_intx; >- uint16_t cmd = 0; >- char *key, *val; >-- int msi_translate, power_mgmt; >-+ int msi_translate, power_mgmt, permissive = 0; >- >- PT_LOG("Assigning real physical device %02x:%02x.%x ...\n", >- r_bus, r_dev, r_func); >-@@ -4366,6 +4396,8 @@ static struct pt_dev * register_real_dev >- else >- PT_LOG("Error: unrecognized value for msitranslate=\n"); >- } >-+ else if (strcmp(key, "permissive") == 0) >-+ permissive = 1; >- else if (strcmp(key, "power_mgmt") == 0) >- { >- if (strcmp(val, "0") == 0) >-@@ -4403,6 +4435,7 @@ static struct pt_dev * register_real_dev >- assigned_device->msi_trans_cap = msi_translate; >- assigned_device->power_mgmt = power_mgmt; >- assigned_device->is_virtfn = pt_dev_is_virtfn(pci_dev); >-+ assigned_device->permissive = permissive; >- pt_iomul_init(assigned_device, r_bus, r_dev, r_func); >- >- /* Initialize virtualized PCI configuration (Extended 256 Bytes) */ >---- a/hw/pass-through.h >-+++ b/hw/pass-through.h >-@@ -242,6 +242,8 @@ struct pt_dev { >- unsigned power_mgmt:1; >- struct pt_pm_info *pm_state; /* PM virtualization */ >- unsigned is_virtfn:1; >-+ unsigned permissive:1; >-+ unsigned permissive_warned:1; >- >- /* io port multiplexing */ >- #define PCI_IOMUL_INVALID_FD (-1) >Index: files/xsa131-qemuu-1.patch >=================================================================== >--- files/xsa131-qemuu-1.patch (revision 394239) >+++ files/xsa131-qemuu-1.patch (working copy) >@@ -1,60 +0,0 @@ >-xen/MSI: don't open-code pass-through of enable bit modifications >- >-Without this the actual XSA-131 fix would cause the enable bit to not >-get set anymore (due to the write back getting suppressed there based >-on the OR of emu_mask, ro_mask, and res_mask). >- >-Note that the fiddling with the enable bit shouldn't really be done by >-qemu, but making this work right (via libxc and the hypervisor) will >-require more extensive changes, which can be postponed until after the >-security issue got addressed. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -1059,7 +1059,6 @@ static int xen_pt_msgctrl_reg_write(XenP >- XenPTMSI *msi = s->msi; >- uint16_t writable_mask = 0; >- uint16_t throughable_mask = 0; >-- uint16_t raw_val; >- >- /* Currently no support for multi-vector */ >- if (*val & PCI_MSI_FLAGS_QSIZE) { >-@@ -1072,12 +1071,11 @@ static int xen_pt_msgctrl_reg_write(XenP >- msi->flags |= cfg_entry->data & ~PCI_MSI_FLAGS_ENABLE; >- >- /* create value for writing to I/O device register */ >-- raw_val = *val; >- throughable_mask = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- /* update MSI */ >-- if (raw_val & PCI_MSI_FLAGS_ENABLE) { >-+ if (*val & PCI_MSI_FLAGS_ENABLE) { >- /* setup MSI pirq for the first time */ >- if (!msi->initialized) { >- /* Init physical one */ >-@@ -1105,10 +1103,6 @@ static int xen_pt_msgctrl_reg_write(XenP >- xen_pt_msi_disable(s); >- } >- >-- /* pass through MSI_ENABLE bit */ >-- *val &= ~PCI_MSI_FLAGS_ENABLE; >-- *val |= raw_val & PCI_MSI_FLAGS_ENABLE; >-- >- return 0; >- } >- >-@@ -1311,7 +1305,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] >- .size = 2, >- .init_val = 0x0000, >- .ro_mask = 0xFF8E, >-- .emu_mask = 0x017F, >-+ .emu_mask = 0x017E, >- .init = xen_pt_msgctrl_reg_init, >- .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_msgctrl_reg_write, >Index: files/xsa131-qemuu-2.patch >=================================================================== >--- files/xsa131-qemuu-2.patch (revision 394239) >+++ files/xsa131-qemuu-2.patch (working copy) >@@ -1,70 +0,0 @@ >-xen/pt: consolidate PM capability emu_mask >- >-There's no point in xen_pt_pmcsr_reg_{read,write}() each ORing >-PCI_PM_CTRL_STATE_MASK and PCI_PM_CTRL_NO_SOFT_RESET into a local >-emu_mask variable - we can have the same effect by setting the field >-descriptor's emu_mask member suitably right away. Note that >-xen_pt_pmcsr_reg_write() is being retained in order to allow later >-patches to be less intrusive. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Acked-by: Ian Campbell <ian.campbell@citrix.com> >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -935,38 +935,21 @@ static XenPTRegInfo xen_pt_emu_reg_pcie[ >- * Power Management Capability >- */ >- >--/* read Power Management Control/Status register */ >--static int xen_pt_pmcsr_reg_read(XenPCIPassthroughState *s, XenPTReg *cfg_entry, >-- uint16_t *value, uint16_t valid_mask) >--{ >-- XenPTRegInfo *reg = cfg_entry->reg; >-- uint16_t valid_emu_mask = reg->emu_mask; >-- >-- valid_emu_mask |= PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_NO_SOFT_RESET; >-- >-- valid_emu_mask = valid_emu_mask & valid_mask; >-- *value = XEN_PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); >-- >-- return 0; >--} >- /* write Power Management Control/Status register */ >- static int xen_pt_pmcsr_reg_write(XenPCIPassthroughState *s, >- XenPTReg *cfg_entry, uint16_t *val, >- uint16_t dev_value, uint16_t valid_mask) >- { >- XenPTRegInfo *reg = cfg_entry->reg; >-- uint16_t emu_mask = reg->emu_mask; >- uint16_t writable_mask = 0; >- uint16_t throughable_mask = 0; >- >-- emu_mask |= PCI_PM_CTRL_STATE_MASK | PCI_PM_CTRL_NO_SOFT_RESET; >-- >- /* modify emulate register */ >-- writable_mask = emu_mask & ~reg->ro_mask & valid_mask; >-+ writable_mask = reg->emu_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; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- return 0; >-@@ -1002,9 +985,9 @@ static XenPTRegInfo xen_pt_emu_reg_pm[] >- .size = 2, >- .init_val = 0x0008, >- .ro_mask = 0xE1FC, >-- .emu_mask = 0x8100, >-+ .emu_mask = 0x810B, >- .init = xen_pt_common_reg_init, >-- .u.w.read = xen_pt_pmcsr_reg_read, >-+ .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_pmcsr_reg_write, >- }, >- { >Index: files/xsa131-qemuu-3.patch >=================================================================== >--- files/xsa131-qemuu-3.patch (revision 394239) >+++ files/xsa131-qemuu-3.patch (working copy) >@@ -1,22 +0,0 @@ >-xen/pt: correctly handle PM status bit >- >-xen_pt_pmcsr_reg_write() needs an adjustment to deal with the RW1C >-nature of the not passed through bit 15 (PCI_PM_CTRL_PME_STATUS). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -950,7 +950,8 @@ static int xen_pt_pmcsr_reg_write(XenPCI >- >- /* create value for writing to I/O device register */ >- throughable_mask = ~reg->emu_mask & valid_mask; >-- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >-+ *val = XEN_PT_MERGE_VALUE(*val, dev_value & ~PCI_PM_CTRL_PME_STATUS, >-+ throughable_mask); >- >- return 0; >- } >Index: files/xsa131-qemuu-4.patch >=================================================================== >--- files/xsa131-qemuu-4.patch (revision 394239) >+++ files/xsa131-qemuu-4.patch (working copy) >@@ -1,248 +0,0 @@ >-xen/pt: split out calculation of throughable mask in PCI config space handling >- >-This is just to avoid having to adjust that calculation later in >-multiple places. >- >-Note that including ->ro_mask in get_throughable_mask()'s calculation >-is only an apparent (i.e. benign) behavioral change: For r/o fields it >-doesn't matter > whether they get passed through - either the same flag >-is also set in emu_mask (then there's no change at all) or the field is >-r/o in hardware (and hence a write won't change it anyway). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -95,6 +95,14 @@ XenPTReg *xen_pt_find_reg(XenPTRegGroup >- return NULL; >- } >- >-+static uint32_t get_throughable_mask(const XenPCIPassthroughState *s, >-+ const XenPTRegInfo *reg, >-+ uint32_t valid_mask) >-+{ >-+ uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask); >-+ >-+ return throughable_mask & valid_mask; >-+} >- >- /**************** >- * general register functions >-@@ -157,14 +165,13 @@ static int xen_pt_byte_reg_write(XenPCIP >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint8_t writable_mask = 0; >-- uint8_t throughable_mask = 0; >-+ uint8_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- return 0; >-@@ -175,14 +182,13 @@ static int xen_pt_word_reg_write(XenPCIP >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- return 0; >-@@ -193,14 +199,13 @@ static int xen_pt_long_reg_write(XenPCIP >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >-+ uint32_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- return 0; >-@@ -292,15 +297,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 throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* 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 = ~reg->emu_mask & valid_mask; >-- >- if (*val & PCI_COMMAND_INTX_DISABLE) { >- throughable_mask |= PCI_COMMAND_INTX_DISABLE; >- } else { >-@@ -456,7 +459,6 @@ static int xen_pt_bar_reg_write(XenPCIPa >- PCIDevice *d = &s->dev; >- const PCIIORegion *r; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t bar_emu_mask = 0; >- uint32_t bar_ro_mask = 0; >- uint32_t r_size = 0; >-@@ -513,8 +515,7 @@ static int xen_pt_bar_reg_write(XenPCIPa >- } >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~bar_emu_mask & valid_mask; >-- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >-+ *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0); >- >- return 0; >- } >-@@ -528,9 +529,8 @@ static int xen_pt_exp_rom_bar_reg_write( >- XenPTRegion *base = NULL; >- PCIDevice *d = (PCIDevice *)&s->dev; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >-+ uint32_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- pcibus_t r_size = 0; >-- uint32_t bar_emu_mask = 0; >- uint32_t bar_ro_mask = 0; >- >- r_size = d->io_regions[PCI_ROM_SLOT].size; >-@@ -539,7 +539,6 @@ static int xen_pt_exp_rom_bar_reg_write( >- r_size = xen_pt_get_emul_size(base->bar_flag, r_size); >- >- /* set emulate mask and read-only mask */ >-- bar_emu_mask = reg->emu_mask; >- bar_ro_mask = (reg->ro_mask | (r_size - 1)) & ~PCI_ROM_ADDRESS_ENABLE; >- >- /* modify emulate register */ >-@@ -547,7 +546,6 @@ static int xen_pt_exp_rom_bar_reg_write( >- cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~bar_emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- return 0; >-@@ -942,14 +940,13 @@ static int xen_pt_pmcsr_reg_write(XenPCI >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* modify emulate register */ >- writable_mask = reg->emu_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 = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value & ~PCI_PM_CTRL_PME_STATUS, >- throughable_mask); >- >-@@ -1042,7 +1039,7 @@ static int xen_pt_msgctrl_reg_write(XenP >- XenPTRegInfo *reg = cfg_entry->reg; >- XenPTMSI *msi = s->msi; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- >- /* Currently no support for multi-vector */ >- if (*val & PCI_MSI_FLAGS_QSIZE) { >-@@ -1055,7 +1052,6 @@ static int xen_pt_msgctrl_reg_write(XenP >- msi->flags |= cfg_entry->data & ~PCI_MSI_FLAGS_ENABLE; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- /* update MSI */ >-@@ -1171,7 +1167,6 @@ static int xen_pt_msgaddr32_reg_write(Xe >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t old_addr = cfg_entry->data; >- >- /* modify emulate register */ >-@@ -1180,8 +1175,7 @@ static int xen_pt_msgaddr32_reg_write(Xe >- s->msi->addr_lo = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >-+ *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_addr) { >-@@ -1199,7 +1193,6 @@ static int xen_pt_msgaddr64_reg_write(Xe >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint32_t writable_mask = 0; >-- uint32_t throughable_mask = 0; >- uint32_t old_addr = cfg_entry->data; >- >- /* check whether the type is 64 bit or not */ >-@@ -1216,8 +1209,7 @@ static int xen_pt_msgaddr64_reg_write(Xe >- s->msi->addr_hi = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >-+ *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_addr) { >-@@ -1239,7 +1231,6 @@ static int xen_pt_msgdata_reg_write(XenP >- XenPTRegInfo *reg = cfg_entry->reg; >- XenPTMSI *msi = s->msi; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >- uint16_t old_data = cfg_entry->data; >- uint32_t offset = reg->offset; >- >-@@ -1257,8 +1248,7 @@ static int xen_pt_msgdata_reg_write(XenP >- msi->data = cfg_entry->data; >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >-- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >-+ *val = XEN_PT_MERGE_VALUE(*val, dev_value, 0); >- >- /* update MSI */ >- if (cfg_entry->data != old_data) { >-@@ -1420,7 +1410,7 @@ static int xen_pt_msixctrl_reg_write(Xen >- { >- XenPTRegInfo *reg = cfg_entry->reg; >- uint16_t writable_mask = 0; >-- uint16_t throughable_mask = 0; >-+ uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask); >- int debug_msix_enabled_old; >- >- /* modify emulate register */ >-@@ -1428,7 +1418,6 @@ static int xen_pt_msixctrl_reg_write(Xen >- cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); >- >- /* create value for writing to I/O device register */ >-- throughable_mask = ~reg->emu_mask & valid_mask; >- *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); >- >- /* update MSI-X */ >Index: files/xsa131-qemuu-5.patch >=================================================================== >--- files/xsa131-qemuu-5.patch (revision 394239) >+++ files/xsa131-qemuu-5.patch (working copy) >@@ -1,22 +0,0 @@ >-xen/pt: mark all PCIe capability bits read-only >- >-xen_pt_emu_reg_pcie[]'s PCI_EXP_DEVCAP needs to cover all bits as read- >-only to avoid unintended write-back (just a precaution, the field ought >-to be read-only in hardware). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -873,7 +873,7 @@ static XenPTRegInfo xen_pt_emu_reg_pcie[ >- .offset = PCI_EXP_DEVCAP, >- .size = 4, >- .init_val = 0x00000000, >-- .ro_mask = 0x1FFCFFFF, >-+ .ro_mask = 0xFFFFFFFF, >- .emu_mask = 0x10000000, >- .init = xen_pt_common_reg_init, >- .u.dw.read = xen_pt_long_reg_read, >Index: files/xsa131-qemuu-6.patch >=================================================================== >--- files/xsa131-qemuu-6.patch (revision 394239) >+++ files/xsa131-qemuu-6.patch (working copy) >@@ -1,75 +0,0 @@ >-xen/pt: mark reserved bits in PCI config space fields >- >-The adjustments are solely to make the subsequent patches work right >-(and hence make the patch set consistent), namely if permissive mode >-(introduced by the last patch) gets used (as both reserved registers >-and reserved fields must be similarly protected from guest access in >-default mode, but the guest should be allowed access to them in >-permissive mode). >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >- >---- a/hw/xen/xen_pt.h >-+++ b/hw/xen/xen_pt.h >-@@ -101,6 +101,8 @@ struct XenPTRegInfo { >- uint32_t offset; >- uint32_t size; >- uint32_t init_val; >-+ /* reg reserved field mask (ON:reserved, OFF:defined) */ >-+ uint32_t res_mask; >- /* reg read only field mask (ON:RO/ROS, OFF:other) */ >- uint32_t ro_mask; >- /* reg emulate field mask (ON:emu, OFF:passthrough) */ >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -580,7 +580,7 @@ static XenPTRegInfo xen_pt_emu_reg_heade >- .offset = PCI_COMMAND, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0xF880, >-+ .res_mask = 0xF880, >- .emu_mask = 0x0743, >- .init = xen_pt_common_reg_init, >- .u.w.read = xen_pt_word_reg_read, >-@@ -605,7 +605,8 @@ static XenPTRegInfo xen_pt_emu_reg_heade >- .offset = PCI_STATUS, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0x06FF, >-+ .res_mask = 0x0007, >-+ .ro_mask = 0x06F8, >- .emu_mask = 0x0010, >- .init = xen_pt_status_reg_init, >- .u.w.read = xen_pt_word_reg_read, >-@@ -982,7 +983,8 @@ static XenPTRegInfo xen_pt_emu_reg_pm[] >- .offset = PCI_PM_CTRL, >- .size = 2, >- .init_val = 0x0008, >-- .ro_mask = 0xE1FC, >-+ .res_mask = 0x00F0, >-+ .ro_mask = 0xE10C, >- .emu_mask = 0x810B, >- .init = xen_pt_common_reg_init, >- .u.w.read = xen_pt_word_reg_read, >-@@ -1278,7 +1280,8 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] >- .offset = PCI_MSI_FLAGS, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0xFF8E, >-+ .res_mask = 0xFE00, >-+ .ro_mask = 0x018E, >- .emu_mask = 0x017E, >- .init = xen_pt_msgctrl_reg_init, >- .u.w.read = xen_pt_word_reg_read, >-@@ -1456,7 +1459,8 @@ static XenPTRegInfo xen_pt_emu_reg_msix[ >- .offset = PCI_MSI_FLAGS, >- .size = 2, >- .init_val = 0x0000, >-- .ro_mask = 0x3FFF, >-+ .res_mask = 0x3800, >-+ .ro_mask = 0x07FF, >- .emu_mask = 0x0000, >- .init = xen_pt_msixctrl_reg_init, >- .u.w.read = xen_pt_word_reg_read, >Index: files/xsa131-qemuu-7.patch >=================================================================== >--- files/xsa131-qemuu-7.patch (revision 394239) >+++ files/xsa131-qemuu-7.patch (working copy) >@@ -1,70 +0,0 @@ >-xen/pt: add a few PCI config space field descriptions >- >-Since the next patch will turn all not explicitly described fields >-read-only by default, those fields that have guest writable bits need >-to be given explicit descriptors. >- >-This is a preparatory patch for XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >---- >-Notes: >-- blindly allowing all VPD reads may still be a problem (out of bounds >- addresses aren't allowed, but the spec doesn't say what the effect >- would be) ==> also an issue in pciback? >-- Vendor Specific cap regs aren't in the table (will become r/o by >- default with this change) >-- many PCIe cap regs aren't in the table (will again become r/o) >-- same for PM cap regs at offsets 6 and 7 >- >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -756,6 +756,15 @@ static XenPTRegInfo xen_pt_emu_reg_vpd[] >- .u.b.write = xen_pt_byte_reg_write, >- }, >- { >-+ .offset = PCI_VPD_ADDR, >-+ .size = 2, >-+ .ro_mask = 0x0003, >-+ .emu_mask = 0x0003, >-+ .init = xen_pt_common_reg_init, >-+ .u.w.read = xen_pt_word_reg_read, >-+ .u.w.write = xen_pt_word_reg_write, >-+ }, >-+ { >- .size = 0, >- }, >- }; >-@@ -891,6 +900,16 @@ static XenPTRegInfo xen_pt_emu_reg_pcie[ >- .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_word_reg_write, >- }, >-+ /* Device Status reg */ >-+ { >-+ .offset = PCI_EXP_DEVSTA, >-+ .size = 2, >-+ .res_mask = 0xFFC0, >-+ .ro_mask = 0x0030, >-+ .init = xen_pt_common_reg_init, >-+ .u.w.read = xen_pt_word_reg_read, >-+ .u.w.write = xen_pt_word_reg_write, >-+ }, >- /* Link Control reg */ >- { >- .offset = PCI_EXP_LNKCTL, >-@@ -902,6 +921,15 @@ static XenPTRegInfo xen_pt_emu_reg_pcie[ >- .u.w.read = xen_pt_word_reg_read, >- .u.w.write = xen_pt_word_reg_write, >- }, >-+ /* Link Status reg */ >-+ { >-+ .offset = PCI_EXP_LNKSTA, >-+ .size = 2, >-+ .ro_mask = 0x3FFF, >-+ .init = xen_pt_common_reg_init, >-+ .u.w.read = xen_pt_word_reg_read, >-+ .u.w.write = xen_pt_word_reg_write, >-+ }, >- /* Device Control 2 reg */ >- { >- .offset = 0x28, >Index: files/xsa131-qemuu-8.patch >=================================================================== >--- files/xsa131-qemuu-8.patch (revision 394239) >+++ files/xsa131-qemuu-8.patch (working copy) >@@ -1,122 +0,0 @@ >-xen/pt: unknown PCI config space fields should be read-only >- >-... by default. Add a per-device "permissive" mode similar to pciback's >-to allow restoring previous behavior (and hence break security again, >-i.e. should be used only for trusted guests). >- >-This is part of XSA-131. >- >-Signed-off-by: Jan Beulich <jbeulich@suse.com> >-Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >-Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>) >---- >-Notes: >-- What purpose does xen_pt_header_type_reg_init() serve (with .emu_mask >- being zero)? >-- In the qemu-trad case no equivalent logic to that setting/using >- direct_pci_{msi_translate,power_mgmt} is being added, as that logic >- seems broken (setting globals from device 0 xenstore settings). >- >---- a/hw/xen/xen_pt.c >-+++ b/hw/xen/xen_pt.c >-@@ -239,6 +239,7 @@ static void xen_pt_pci_write_config(PCID >- XenPTReg *reg_entry = NULL; >- uint32_t find_addr = addr; >- XenPTRegInfo *reg = NULL; >-+ bool wp_flag = false; >- >- if (xen_pt_pci_config_access_check(d, addr, len)) { >- return; >-@@ -280,6 +281,10 @@ static void xen_pt_pci_write_config(PCID >- >- /* pass directly to the real device for passthrough type register group */ >- if (reg_grp_entry == NULL) { >-+ if (!s->permissive) { >-+ wb_mask = 0; >-+ wp_flag = true; >-+ } >- goto out; >- } >- >-@@ -300,12 +305,15 @@ static void xen_pt_pci_write_config(PCID >- uint32_t real_offset = reg_grp_entry->base_offset + reg->offset; >- uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3); >- uint8_t *ptr_val = NULL; >-+ uint32_t wp_mask = reg->emu_mask | reg->ro_mask; >- >- 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)) >-+ if (!s->permissive) { >-+ wp_mask |= reg->res_mask; >-+ } >-+ if (wp_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { >-+ wb_mask &= ~((wp_mask >> ((find_addr - real_offset) << 3)) >- << ((len - emul_len) << 3)); >- } >- >-@@ -349,6 +357,16 @@ static void xen_pt_pci_write_config(PCID >- } else { >- /* nothing to do with passthrough type register, >- * continue to find next byte */ >-+ if (!s->permissive) { >-+ wb_mask &= ~(0xff << ((len - emul_len) << 3)); >-+ /* Unused BARs will make it here, but we don't want to issue >-+ * warnings for writes to them (bogus writes get dealt with >-+ * above). >-+ */ >-+ if (index < 0) { >-+ wp_flag = true; >-+ } >-+ } >- emul_len--; >- find_addr++; >- } >-@@ -360,6 +378,13 @@ static void xen_pt_pci_write_config(PCID >- memory_region_transaction_commit(); >- >- out: >-+ if (wp_flag && !s->permissive_warned) { >-+ s->permissive_warned = true; >-+ xen_pt_log(d, "Write-back to unknown field 0x%02x (partially) inhibited (0x%0*x)\n", >-+ addr, len * 2, wb_mask); >-+ xen_pt_log(d, "If the device doesn't work, try enabling permissive mode\n"); >-+ xen_pt_log(d, "(unsafe) and if it helps report the problem to xen-devel\n"); >-+ } >- for (index = 0; wb_mask; index += len) { >- /* unknown regs are passed through */ >- while (!(wb_mask & 0xff)) { >-@@ -821,6 +846,7 @@ static void xen_pt_unregister_device(PCI >- >- static Property xen_pci_passthrough_properties[] = { >- DEFINE_PROP_PCI_HOST_DEVADDR("hostaddr", XenPCIPassthroughState, hostaddr), >-+ DEFINE_PROP_BOOL("permissive", XenPCIPassthroughState, permissive, false), >- DEFINE_PROP_END_OF_LIST(), >- }; >- >---- a/hw/xen/xen_pt.h >-+++ b/hw/xen/xen_pt.h >-@@ -197,6 +197,8 @@ struct XenPCIPassthroughState { >- >- PCIHostDeviceAddress hostaddr; >- bool is_virtfn; >-+ bool permissive; >-+ bool permissive_warned; >- XenHostPCIDevice real_device; >- XenPTRegion bases[PCI_NUM_REGIONS]; /* Access regions */ >- QLIST_HEAD(, XenPTRegGroup) reg_grps; >---- a/hw/xen/xen_pt_config_init.c >-+++ b/hw/xen/xen_pt_config_init.c >-@@ -101,6 +101,10 @@ static uint32_t get_throughable_mask(con >- { >- uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask); >- >-+ if (!s->permissive) { >-+ throughable_mask &= ~reg->res_mask; >-+ } >-+ >- return throughable_mask & valid_mask; >- } >- >Index: files/xsa133-qemut.patch >=================================================================== >--- files/xsa133-qemut.patch (revision 394239) >+++ files/xsa133-qemut.patch (working copy) >@@ -1,80 +0,0 @@ >-From ac7ddbe342d7aa2303c39ca731cc6229dbbd739b Mon Sep 17 00:00:00 2001 >-From: Petr Matousek <pmatouse@redhat.com> >-Date: Wed, 6 May 2015 09:48:59 +0200 >-Subject: [PATCH] fdc: force the fifo access to be in bounds of the allocated buffer >- >-During processing of certain commands such as FD_CMD_READ_ID and >-FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could >-get out of bounds leading to memory corruption with values coming >-from the guest. >- >-Fix this by making sure that the index is always bounded by the >-allocated memory. >- >-This is CVE-2015-3456. >- >-Signed-off-by: Petr Matousek <pmatouse@redhat.com> >-Reviewed-by: John Snow <jsnow@redhat.com> >---- >- hw/fdc.c | 17 +++++++++++------ >- 1 file changed, 11 insertions(+), 6 deletions(-) >- >-diff --git a/hw/fdc.c b/hw/fdc.c >-index b00a4ec..aba02e4 100644 >---- a/hw/fdc.c >-+++ b/hw/fdc.c >-@@ -1318,7 +1318,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) >- { >- fdrive_t *cur_drv; >- uint32_t retval = 0; >-- int pos; >-+ uint32_t pos; >- >- cur_drv = get_cur_drv(fdctrl); >- fdctrl->dsr &= ~FD_DSR_PWRDOWN; >-@@ -1327,8 +1327,8 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) >- return 0; >- } >- pos = fdctrl->data_pos; >-+ pos %= FD_SECTOR_LEN; >- if (fdctrl->msr & FD_MSR_NONDMA) { >-- pos %= FD_SECTOR_LEN; >- if (pos == 0) { >- if (fdctrl->data_pos != 0) >- if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { >-@@ -1673,10 +1673,13 @@ static void fdctrl_handle_option (fdctrl_t *fdctrl, int direction) >- static void fdctrl_handle_drive_specification_command (fdctrl_t *fdctrl, int direction) >- { >- fdrive_t *cur_drv = get_cur_drv(fdctrl); >-+ uint32_t pos; >- >-- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) { >-+ pos = fdctrl->data_pos - 1; >-+ pos %= FD_SECTOR_LEN; >-+ if (fdctrl->fifo[pos] & 0x80) { >- /* Command parameters done */ >-- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) { >-+ if (fdctrl->fifo[pos] & 0x40) { >- fdctrl->fifo[0] = fdctrl->fifo[1]; >- fdctrl->fifo[2] = 0; >- fdctrl->fifo[3] = 0; >-@@ -1771,7 +1774,7 @@ static uint8_t command_to_handler[256]; >- static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) >- { >- fdrive_t *cur_drv; >-- int pos; >-+ uint32_t pos; >- >- /* Reset mode */ >- if (!(fdctrl->dor & FD_DOR_nRESET)) { >-@@ -1817,7 +1820,9 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) >- } >- >- FLOPPY_DPRINTF("%s: %02x\n", __func__, value); >-- fdctrl->fifo[fdctrl->data_pos++] = value; >-+ pos = fdctrl->data_pos++; >-+ pos %= FD_SECTOR_LEN; >-+ fdctrl->fifo[pos] = value; >- if (fdctrl->data_pos == fdctrl->data_len) { >- /* We now have all parameters >- * and will be able to treat the command >Index: files/xsa133-qemuu.patch >=================================================================== >--- files/xsa133-qemuu.patch (revision 394239) >+++ files/xsa133-qemuu.patch (working copy) >@@ -1,84 +0,0 @@ >-From ac7ddbe342d7aa2303c39ca731cc6229dbbd739b Mon Sep 17 00:00:00 2001 >-From: Petr Matousek <pmatouse@redhat.com> >-Date: Wed, 6 May 2015 09:48:59 +0200 >-Subject: [PATCH] fdc: force the fifo access to be in bounds of the allocated buffer >- >-During processing of certain commands such as FD_CMD_READ_ID and >-FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could >-get out of bounds leading to memory corruption with values coming >-from the guest. >- >-Fix this by making sure that the index is always bounded by the >-allocated memory. >- >-This is CVE-2015-3456. >- >-Signed-off-by: Petr Matousek <pmatouse@redhat.com> >-Reviewed-by: John Snow <jsnow@redhat.com> >---- >- hw/block/fdc.c | 17 +++++++++++------ >- 1 file changed, 11 insertions(+), 6 deletions(-) >- >-diff --git a/hw/block/fdc.c b/hw/block/fdc.c >-index f72a392..d8a8edd 100644 >---- a/hw/block/fdc.c >-+++ b/hw/block/fdc.c >-@@ -1497,7 +1497,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl) >- { >- FDrive *cur_drv; >- uint32_t retval = 0; >-- int pos; >-+ uint32_t pos; >- >- cur_drv = get_cur_drv(fdctrl); >- fdctrl->dsr &= ~FD_DSR_PWRDOWN; >-@@ -1506,8 +1506,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl) >- return 0; >- } >- pos = fdctrl->data_pos; >-+ pos %= FD_SECTOR_LEN; >- if (fdctrl->msr & FD_MSR_NONDMA) { >-- pos %= FD_SECTOR_LEN; >- if (pos == 0) { >- if (fdctrl->data_pos != 0) >- if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { >-@@ -1852,10 +1852,13 @@ static void fdctrl_handle_option(FDCtrl *fdctrl, int direction) >- static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction) >- { >- FDrive *cur_drv = get_cur_drv(fdctrl); >-+ uint32_t pos; >- >-- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) { >-+ pos = fdctrl->data_pos - 1; >-+ pos %= FD_SECTOR_LEN; >-+ if (fdctrl->fifo[pos] & 0x80) { >- /* Command parameters done */ >-- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) { >-+ if (fdctrl->fifo[pos] & 0x40) { >- fdctrl->fifo[0] = fdctrl->fifo[1]; >- fdctrl->fifo[2] = 0; >- fdctrl->fifo[3] = 0; >-@@ -1955,7 +1958,7 @@ static uint8_t command_to_handler[256]; >- static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) >- { >- FDrive *cur_drv; >-- int pos; >-+ uint32_t pos; >- >- /* Reset mode */ >- if (!(fdctrl->dor & FD_DOR_nRESET)) { >-@@ -2004,7 +2007,9 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) >- } >- >- FLOPPY_DPRINTF("%s: %02x\n", __func__, value); >-- fdctrl->fifo[fdctrl->data_pos++] = value; >-+ pos = fdctrl->data_pos++; >-+ pos %= FD_SECTOR_LEN; >-+ fdctrl->fifo[pos] = value; >- if (fdctrl->data_pos == fdctrl->data_len) { >- /* We now have all parameters >- * and will be able to treat the command >--- >-2.1.0 >- >- >Index: files/xsa135-qemuu-4.5-1.patch >=================================================================== >--- files/xsa135-qemuu-4.5-1.patch (revision 394239) >+++ files/xsa135-qemuu-4.5-1.patch (working copy) >@@ -1,94 +0,0 @@ >-pcnet: fix Negative array index read >- >-From: Gonglei <arei.gonglei@huawei.com> >- >-s->xmit_pos maybe assigned to a negative value (-1), >-but in this branch variable s->xmit_pos as an index to >-array s->buffer. Let's add a check for s->xmit_pos. >- >-upstream-commit-id: 7b50d00911ddd6d56a766ac5671e47304c20a21b >- >-Signed-off-by: Gonglei <arei.gonglei@huawei.com> >-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> >-Reviewed-by: Jason Wang <jasowang@redhat.com> >-Reviewed-by: Jason Wang <jasowang@redhat.com> >-Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >- >-diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c >-index d344c15..f409b92 100644 >---- a/hw/net/pcnet.c >-+++ b/hw/net/pcnet.c >-@@ -1212,7 +1212,7 @@ static void pcnet_transmit(PCNetState *s) >- hwaddr xmit_cxda = 0; >- int count = CSR_XMTRL(s)-1; >- int add_crc = 0; >-- >-+ int bcnt; >- s->xmit_pos = -1; >- >- if (!CSR_TXON(s)) { >-@@ -1247,35 +1247,40 @@ static void pcnet_transmit(PCNetState *s) >- s->xmit_pos = -1; >- goto txdone; >- } >-+ >-+ if (s->xmit_pos < 0) { >-+ goto txdone; >-+ } >-+ >-+ bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT); >-+ s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr), >-+ s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); >-+ s->xmit_pos += bcnt; >-+ >- if (!GET_FIELD(tmd.status, TMDS, ENP)) { >-- int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT); >-- s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr), >-- s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); >-- s->xmit_pos += bcnt; >-- } else if (s->xmit_pos >= 0) { >-- int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT); >-- s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr), >-- s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); >-- s->xmit_pos += bcnt; >-+ goto txdone; >-+ } >-+ >- #ifdef PCNET_DEBUG >-- printf("pcnet_transmit size=%d\n", s->xmit_pos); >-+ printf("pcnet_transmit size=%d\n", s->xmit_pos); >- #endif >-- if (CSR_LOOP(s)) { >-- if (BCR_SWSTYLE(s) == 1) >-- add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS); >-- s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC; >-- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos); >-- s->looptest = 0; >-- } else >-- if (s->nic) >-- qemu_send_packet(qemu_get_queue(s->nic), s->buffer, >-- s->xmit_pos); >-- >-- s->csr[0] &= ~0x0008; /* clear TDMD */ >-- s->csr[4] |= 0x0004; /* set TXSTRT */ >-- s->xmit_pos = -1; >-+ if (CSR_LOOP(s)) { >-+ if (BCR_SWSTYLE(s) == 1) >-+ add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS); >-+ s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC; >-+ pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos); >-+ s->looptest = 0; >-+ } else { >-+ if (s->nic) { >-+ qemu_send_packet(qemu_get_queue(s->nic), s->buffer, >-+ s->xmit_pos); >-+ } >- } >- >-+ s->csr[0] &= ~0x0008; /* clear TDMD */ >-+ s->csr[4] |= 0x0004; /* set TXSTRT */ >-+ s->xmit_pos = -1; >-+ >- txdone: >- SET_FIELD(&tmd.status, TMDS, OWN, 0); >- TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s))); >Index: files/xsa135-qemuu-4.5-2.patch >=================================================================== >--- files/xsa135-qemuu-4.5-2.patch (revision 394239) >+++ files/xsa135-qemuu-4.5-2.patch (working copy) >@@ -1,45 +0,0 @@ >-From 2630672ab22255de252f877709851c0557a1c647 Mon Sep 17 00:00:00 2001 >-From: Petr Matousek <pmatouse@redhat.com> >-Date: Sun, 24 May 2015 10:53:44 +0200 >-Subject: [PATCH] pcnet: force the buffer access to be in bounds during tx >- >-4096 is the maximum length per TMD and it is also currently the size of >-the relay buffer pcnet driver uses for sending the packet data to QEMU >-for further processing. With packet spanning multiple TMDs it can >-happen that the overall packet size will be bigger than sizeof(buffer), >-which results in memory corruption. >- >-Fix this by only allowing to queue maximum sizeof(buffer) bytes. >- >-This is CVE-2015-3209. >- >-Signed-off-by: Petr Matousek <pmatouse@redhat.com> >-Reported-by: Matt Tait <matttait@google.com> >-Reviewed-by: Peter Maydell <peter.maydell@linaro.org> >-Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> >---- >- hw/net/pcnet.c | 8 ++++++++ >- 1 file changed, 8 insertions(+) >- >-diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c >-index bdfd38f..6d32e4c 100644 >---- a/hw/net/pcnet.c >-+++ b/hw/net/pcnet.c >-@@ -1241,6 +1241,14 @@ static void pcnet_transmit(PCNetState *s) >- } >- >- bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT); >-+ >-+ /* if multi-tmd packet outsizes s->buffer then skip it silently. >-+ Note: this is not what real hw does */ >-+ if (s->xmit_pos + bcnt > sizeof(s->buffer)) { >-+ s->xmit_pos = -1; >-+ goto txdone; >-+ } >-+ >- s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr), >- s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); >- s->xmit_pos += bcnt; >--- >-2.1.0 >- >Index: files/xsa139-qemuu-4.5.patch >=================================================================== >--- files/xsa139-qemuu-4.5.patch (revision 0) >+++ files/xsa139-qemuu-4.5.patch (working copy) >@@ -0,0 +1,38 @@ >+pci_piix3_xen_ide_unplug should completely unhook the unplugged >+IDEDevice from the corresponding BlockBackend, otherwise the next call >+to release_drive will try to detach the drive again. >+ >+Suggested-by: Kevin Wolf <kwolf@redhat.com> >+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >+--- >+ hw/ide/piix.c | 7 +++++++ >+ 1 file changed, 7 insertions(+) >+ >+diff --git a/hw/ide/piix.c b/hw/ide/piix.c >+index 40757eb..0524dce 100644 >+--- a/hw/ide/piix.c >++++ b/hw/ide/piix.c >+@@ -172,6 +172,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev) >+ PCIIDEState *pci_ide; >+ DriveInfo *di; >+ int i = 0; >++ IDEDevice *idedev; >+ >+ pci_ide = PCI_IDE(dev); >+ >+@@ -184,6 +185,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev) >+ } >+ bdrv_close(di->bdrv); >+ pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; >++ if (!(i % 2)) { >++ idedev = pci_ide->bus[di->bus].master; >++ } else { >++ idedev = pci_ide->bus[di->bus].slave; >++ } >++ idedev->conf.bs = NULL; >+ drive_put_ref(di); >+ } >+ } >+-- >+2.1.4 >+ > >Property changes on: files/xsa139-qemuu-4.5.patch >___________________________________________________________________ >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-1.patch >=================================================================== >--- files/xsa140-qemuu-unstable-1.patch (revision 0) >+++ files/xsa140-qemuu-unstable-1.patch (working copy) >@@ -0,0 +1,82 @@ >+From 5e0c290415b9d57077a86e70c8e6a058868334d3 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:16:58 +0100 >+Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing >+ >+Transmit offload needs to parse packet headers. If header fields have >+unexpected values the offload processing is skipped. >+ >+The code currently uses nested ifs because there is relatively little >+input validation. The next patches will add missing input validation >+and a goto label is more appropriate to avoid deep if statement nesting. >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 41 ++++++++++++++++++++++------------------- >+ 1 file changed, 22 insertions(+), 19 deletions(-) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index 5f0197c..91ba33b 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2174,28 +2174,30 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ size_t eth_payload_len = 0; >+ >+ int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); >+- if (proto == ETH_P_IP) >++ if (proto != ETH_P_IP) >+ { >+- DPRINTF("+++ C+ mode has IP packet\n"); >+- >+- /* not aligned */ >+- eth_payload_data = saved_buffer + ETH_HLEN; >+- eth_payload_len = saved_size - ETH_HLEN; >+- >+- ip = (ip_header*)eth_payload_data; >+- >+- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { >+- DPRINTF("+++ C+ mode packet has bad IP version %d " >+- "expected %d\n", IP_HEADER_VERSION(ip), >+- IP_HEADER_VERSION_4); >+- ip = NULL; >+- } else { >+- hlen = IP_HEADER_LENGTH(ip); >+- ip_protocol = ip->ip_p; >+- ip_data_len = be16_to_cpu(ip->ip_len) - hlen; >+- } >++ goto skip_offload; >+ } >+ >++ DPRINTF("+++ C+ mode has IP packet\n"); >++ >++ /* not aligned */ >++ eth_payload_data = saved_buffer + ETH_HLEN; >++ eth_payload_len = saved_size - ETH_HLEN; >++ >++ ip = (ip_header*)eth_payload_data; >++ >++ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { >++ DPRINTF("+++ C+ mode packet has bad IP version %d " >++ "expected %d\n", IP_HEADER_VERSION(ip), >++ IP_HEADER_VERSION_4); >++ goto skip_offload; >++ } >++ >++ hlen = IP_HEADER_LENGTH(ip); >++ ip_protocol = ip->ip_p; >++ ip_data_len = be16_to_cpu(ip->ip_len) - hlen; >++ >+ if (ip) >+ { >+ if (txdw0 & CP_TX_IPCS) >+@@ -2391,6 +2393,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ } >+ } >+ >++skip_offload: >+ /* update tally counter */ >+ ++s->tally_counters.TxOk; >+ >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-1.patch >___________________________________________________________________ >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-2.patch >=================================================================== >--- files/xsa140-qemuu-unstable-2.patch (revision 0) >+++ files/xsa140-qemuu-unstable-2.patch (working copy) >@@ -0,0 +1,373 @@ >+From 2d7d80e8dc160904fa7276cc05da26c062a50066 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:16:59 +0100 >+Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement >+ >+The previous patch stopped using the ip pointer as an indicator that the >+IP header is present. When we reach the if (ip) {...} statement we know >+ip is always non-NULL. >+ >+Remove the if statement to reduce nesting. >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 305 +++++++++++++++++++++++++++---------------------------- >+ 1 file changed, 151 insertions(+), 154 deletions(-) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index 91ba33b..2f12d42 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2198,198 +2198,195 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ ip_protocol = ip->ip_p; >+ ip_data_len = be16_to_cpu(ip->ip_len) - hlen; >+ >+- if (ip) >++ if (txdw0 & CP_TX_IPCS) >+ { >+- if (txdw0 & CP_TX_IPCS) >+- { >+- DPRINTF("+++ C+ mode need IP checksum\n"); >++ DPRINTF("+++ C+ mode need IP checksum\n"); >+ >+- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ >+- /* bad packet header len */ >+- /* or packet too short */ >+- } >+- else >+- { >+- ip->ip_sum = 0; >+- ip->ip_sum = ip_checksum(ip, hlen); >+- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", >+- hlen, ip->ip_sum); >+- } >++ if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ >++ /* bad packet header len */ >++ /* or packet too short */ >+ } >+- >+- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) >++ else >+ { >+- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; >++ ip->ip_sum = 0; >++ ip->ip_sum = ip_checksum(ip, hlen); >++ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", >++ hlen, ip->ip_sum); >++ } >++ } >+ >+- DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " >+- "frame data %d specified MSS=%d\n", ETH_MTU, >+- ip_data_len, saved_size - ETH_HLEN, large_send_mss); >++ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) >++ { >++ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; >+ >+- int tcp_send_offset = 0; >+- int send_count = 0; >++ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " >++ "frame data %d specified MSS=%d\n", ETH_MTU, >++ ip_data_len, saved_size - ETH_HLEN, large_send_mss); >+ >+- /* maximum IP header length is 60 bytes */ >+- uint8_t saved_ip_header[60]; >++ int tcp_send_offset = 0; >++ int send_count = 0; >+ >+- /* save IP header template; data area is used in tcp checksum calculation */ >+- memcpy(saved_ip_header, eth_payload_data, hlen); >++ /* maximum IP header length is 60 bytes */ >++ uint8_t saved_ip_header[60]; >+ >+- /* a placeholder for checksum calculation routine in tcp case */ >+- uint8_t *data_to_checksum = eth_payload_data + hlen - 12; >+- // size_t data_to_checksum_len = eth_payload_len - hlen + 12; >++ /* save IP header template; data area is used in tcp checksum calculation */ >++ memcpy(saved_ip_header, eth_payload_data, hlen); >+ >+- /* pointer to TCP header */ >+- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); >++ /* a placeholder for checksum calculation routine in tcp case */ >++ uint8_t *data_to_checksum = eth_payload_data + hlen - 12; >++ // size_t data_to_checksum_len = eth_payload_len - hlen + 12; >+ >+- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); >++ /* pointer to TCP header */ >++ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); >+ >+- /* ETH_MTU = ip header len + tcp header len + payload */ >+- int tcp_data_len = ip_data_len - tcp_hlen; >+- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; >++ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); >+ >+- DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " >+- "data len %d TCP chunk size %d\n", ip_data_len, >+- tcp_hlen, tcp_data_len, tcp_chunk_size); >++ /* ETH_MTU = ip header len + tcp header len + payload */ >++ int tcp_data_len = ip_data_len - tcp_hlen; >++ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; >+ >+- /* note the cycle below overwrites IP header data, >+- but restores it from saved_ip_header before sending packet */ >++ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " >++ "data len %d TCP chunk size %d\n", ip_data_len, >++ tcp_hlen, tcp_data_len, tcp_chunk_size); >+ >+- int is_last_frame = 0; >++ /* note the cycle below overwrites IP header data, >++ but restores it from saved_ip_header before sending packet */ >+ >+- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) >+- { >+- uint16_t chunk_size = tcp_chunk_size; >+- >+- /* check if this is the last frame */ >+- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) >+- { >+- is_last_frame = 1; >+- chunk_size = tcp_data_len - tcp_send_offset; >+- } >+- >+- DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", >+- be32_to_cpu(p_tcp_hdr->th_seq)); >+- >+- /* add 4 TCP pseudoheader fields */ >+- /* copy IP source and destination fields */ >+- memcpy(data_to_checksum, saved_ip_header + 12, 8); >+- >+- DPRINTF("+++ C+ mode TSO calculating TCP checksum for " >+- "packet with %d bytes data\n", tcp_hlen + >+- chunk_size); >+- >+- if (tcp_send_offset) >+- { >+- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); >+- } >+- >+- /* keep PUSH and FIN flags only for the last frame */ >+- if (!is_last_frame) >+- { >+- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); >+- } >+- >+- /* recalculate TCP checksum */ >+- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; >+- p_tcpip_hdr->zeros = 0; >+- p_tcpip_hdr->ip_proto = IP_PROTO_TCP; >+- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); >+- >+- p_tcp_hdr->th_sum = 0; >+- >+- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); >+- DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", >+- tcp_checksum); >+- >+- p_tcp_hdr->th_sum = tcp_checksum; >+- >+- /* restore IP header */ >+- memcpy(eth_payload_data, saved_ip_header, hlen); >+- >+- /* set IP data length and recalculate IP checksum */ >+- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); >+- >+- /* increment IP id for subsequent frames */ >+- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id)); >+- >+- ip->ip_sum = 0; >+- ip->ip_sum = ip_checksum(eth_payload_data, hlen); >+- DPRINTF("+++ C+ mode TSO IP header len=%d " >+- "checksum=%04x\n", hlen, ip->ip_sum); >+- >+- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; >+- DPRINTF("+++ C+ mode TSO transferring packet size " >+- "%d\n", tso_send_size); >+- rtl8139_transfer_frame(s, saved_buffer, tso_send_size, >+- 0, (uint8_t *) dot1q_buffer); >+- >+- /* add transferred count to TCP sequence number */ >+- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); >+- ++send_count; >+- } >++ int is_last_frame = 0; >+ >+- /* Stop sending this frame */ >+- saved_size = 0; >+- } >+- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) >++ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) >+ { >+- DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); >++ uint16_t chunk_size = tcp_chunk_size; >+ >+- /* maximum IP header length is 60 bytes */ >+- uint8_t saved_ip_header[60]; >+- memcpy(saved_ip_header, eth_payload_data, hlen); >++ /* check if this is the last frame */ >++ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) >++ { >++ is_last_frame = 1; >++ chunk_size = tcp_data_len - tcp_send_offset; >++ } >+ >+- uint8_t *data_to_checksum = eth_payload_data + hlen - 12; >+- // size_t data_to_checksum_len = eth_payload_len - hlen + 12; >++ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", >++ be32_to_cpu(p_tcp_hdr->th_seq)); >+ >+ /* add 4 TCP pseudoheader fields */ >+ /* copy IP source and destination fields */ >+ memcpy(data_to_checksum, saved_ip_header + 12, 8); >+ >+- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) >++ DPRINTF("+++ C+ mode TSO calculating TCP checksum for " >++ "packet with %d bytes data\n", tcp_hlen + >++ chunk_size); >++ >++ if (tcp_send_offset) >+ { >+- DPRINTF("+++ C+ mode calculating TCP checksum for " >+- "packet with %d bytes data\n", ip_data_len); >++ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); >++ } >+ >+- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; >+- p_tcpip_hdr->zeros = 0; >+- p_tcpip_hdr->ip_proto = IP_PROTO_TCP; >+- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); >++ /* keep PUSH and FIN flags only for the last frame */ >++ if (!is_last_frame) >++ { >++ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); >++ } >+ >+- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); >++ /* recalculate TCP checksum */ >++ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; >++ p_tcpip_hdr->zeros = 0; >++ p_tcpip_hdr->ip_proto = IP_PROTO_TCP; >++ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); >+ >+- p_tcp_hdr->th_sum = 0; >++ p_tcp_hdr->th_sum = 0; >+ >+- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); >+- DPRINTF("+++ C+ mode TCP checksum %04x\n", >+- tcp_checksum); >++ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); >++ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", >++ tcp_checksum); >+ >+- p_tcp_hdr->th_sum = tcp_checksum; >+- } >+- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) >+- { >+- DPRINTF("+++ C+ mode calculating UDP checksum for " >+- "packet with %d bytes data\n", ip_data_len); >++ p_tcp_hdr->th_sum = tcp_checksum; >+ >+- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; >+- p_udpip_hdr->zeros = 0; >+- p_udpip_hdr->ip_proto = IP_PROTO_UDP; >+- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); >++ /* restore IP header */ >++ memcpy(eth_payload_data, saved_ip_header, hlen); >+ >+- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); >++ /* set IP data length and recalculate IP checksum */ >++ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); >+ >+- p_udp_hdr->uh_sum = 0; >++ /* increment IP id for subsequent frames */ >++ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id)); >+ >+- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); >+- DPRINTF("+++ C+ mode UDP checksum %04x\n", >+- udp_checksum); >++ ip->ip_sum = 0; >++ ip->ip_sum = ip_checksum(eth_payload_data, hlen); >++ DPRINTF("+++ C+ mode TSO IP header len=%d " >++ "checksum=%04x\n", hlen, ip->ip_sum); >+ >+- p_udp_hdr->uh_sum = udp_checksum; >+- } >++ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; >++ DPRINTF("+++ C+ mode TSO transferring packet size " >++ "%d\n", tso_send_size); >++ rtl8139_transfer_frame(s, saved_buffer, tso_send_size, >++ 0, (uint8_t *) dot1q_buffer); >+ >+- /* restore IP header */ >+- memcpy(eth_payload_data, saved_ip_header, hlen); >++ /* add transferred count to TCP sequence number */ >++ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); >++ ++send_count; >+ } >++ >++ /* Stop sending this frame */ >++ saved_size = 0; >++ } >++ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) >++ { >++ DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); >++ >++ /* maximum IP header length is 60 bytes */ >++ uint8_t saved_ip_header[60]; >++ memcpy(saved_ip_header, eth_payload_data, hlen); >++ >++ uint8_t *data_to_checksum = eth_payload_data + hlen - 12; >++ // size_t data_to_checksum_len = eth_payload_len - hlen + 12; >++ >++ /* add 4 TCP pseudoheader fields */ >++ /* copy IP source and destination fields */ >++ memcpy(data_to_checksum, saved_ip_header + 12, 8); >++ >++ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) >++ { >++ DPRINTF("+++ C+ mode calculating TCP checksum for " >++ "packet with %d bytes data\n", ip_data_len); >++ >++ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; >++ p_tcpip_hdr->zeros = 0; >++ p_tcpip_hdr->ip_proto = IP_PROTO_TCP; >++ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); >++ >++ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); >++ >++ p_tcp_hdr->th_sum = 0; >++ >++ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); >++ DPRINTF("+++ C+ mode TCP checksum %04x\n", >++ tcp_checksum); >++ >++ p_tcp_hdr->th_sum = tcp_checksum; >++ } >++ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) >++ { >++ DPRINTF("+++ C+ mode calculating UDP checksum for " >++ "packet with %d bytes data\n", ip_data_len); >++ >++ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; >++ p_udpip_hdr->zeros = 0; >++ p_udpip_hdr->ip_proto = IP_PROTO_UDP; >++ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); >++ >++ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); >++ >++ p_udp_hdr->uh_sum = 0; >++ >++ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); >++ DPRINTF("+++ C+ mode UDP checksum %04x\n", >++ udp_checksum); >++ >++ p_udp_hdr->uh_sum = udp_checksum; >++ } >++ >++ /* restore IP header */ >++ memcpy(eth_payload_data, saved_ip_header, hlen); >+ } >+ } >+ >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-2.patch >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-3.patch >=================================================================== >--- files/xsa140-qemuu-unstable-3.patch (revision 0) >+++ files/xsa140-qemuu-unstable-3.patch (working copy) >@@ -0,0 +1,39 @@ >+From 043d28507ef7c5fdc34866f5e3b27a72bd0cd072 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:17:00 +0100 >+Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header >+ >+Transmit offload features access Ethernet and IP headers the packet. If >+the packet is too short we must not attempt to access header fields: >+ >+ int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); >+ ... >+ eth_payload_data = saved_buffer + ETH_HLEN; >+ ... >+ ip = (ip_header*)eth_payload_data; >+ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 5 +++++ >+ 1 file changed, 5 insertions(+) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index 2f12d42..d377b6b 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2164,6 +2164,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ { >+ DPRINTF("+++ C+ mode offloaded task checksum\n"); >+ >++ /* Large enough for Ethernet and IP headers? */ >++ if (saved_size < ETH_HLEN + sizeof(ip_header)) { >++ goto skip_offload; >++ } >++ >+ /* ip packet header */ >+ ip_header *ip = NULL; >+ int hlen = 0; >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-3.patch >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-4.patch >=================================================================== >--- files/xsa140-qemuu-unstable-4.patch (revision 0) >+++ files/xsa140-qemuu-unstable-4.patch (working copy) >@@ -0,0 +1,53 @@ >+From 5a75d242fe019d05b46ef9bc330a6892525c84a7 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:17:01 +0100 >+Subject: [PATCH 4/7] rtl8139: check IP Header Length field >+ >+The IP Header Length field was only checked in the IP checksum case, but >+is used in other cases too. >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 19 ++++++++----------- >+ 1 file changed, 8 insertions(+), 11 deletions(-) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index d377b6b..cd5ac05 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2200,6 +2200,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ } >+ >+ hlen = IP_HEADER_LENGTH(ip); >++ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) { >++ goto skip_offload; >++ } >++ >+ ip_protocol = ip->ip_p; >+ ip_data_len = be16_to_cpu(ip->ip_len) - hlen; >+ >+@@ -2207,17 +2211,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ { >+ DPRINTF("+++ C+ mode need IP checksum\n"); >+ >+- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ >+- /* bad packet header len */ >+- /* or packet too short */ >+- } >+- else >+- { >+- ip->ip_sum = 0; >+- ip->ip_sum = ip_checksum(ip, hlen); >+- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", >+- hlen, ip->ip_sum); >+- } >++ ip->ip_sum = 0; >++ ip->ip_sum = ip_checksum(ip, hlen); >++ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", >++ hlen, ip->ip_sum); >+ } >+ >+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-4.patch >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-5.patch >=================================================================== >--- files/xsa140-qemuu-unstable-5.patch (revision 0) >+++ files/xsa140-qemuu-unstable-5.patch (working copy) >@@ -0,0 +1,34 @@ >+From 6c79ea275d72bc1fd88bdcf1e7d231b2c9c865de Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:17:02 +0100 >+Subject: [PATCH 5/7] rtl8139: check IP Total Length field >+ >+The IP Total Length field includes the IP header and data. Make sure it >+is valid and does not exceed the Ethernet payload size. >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 7 ++++++- >+ 1 file changed, 6 insertions(+), 1 deletion(-) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index cd5ac05..ed2b23b 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2205,7 +2205,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ } >+ >+ ip_protocol = ip->ip_p; >+- ip_data_len = be16_to_cpu(ip->ip_len) - hlen; >++ >++ ip_data_len = be16_to_cpu(ip->ip_len); >++ if (ip_data_len < hlen || ip_data_len > eth_payload_len) { >++ goto skip_offload; >++ } >++ ip_data_len -= hlen; >+ >+ if (txdw0 & CP_TX_IPCS) >+ { >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-5.patch >___________________________________________________________________ >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-6.patch >=================================================================== >--- files/xsa140-qemuu-unstable-6.patch (revision 0) >+++ files/xsa140-qemuu-unstable-6.patch (working copy) >@@ -0,0 +1,35 @@ >+From 30aa7be430e7c982e9163f3bcc745d3aa57b6aa4 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:17:03 +0100 >+Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header >+ >+TCP Large Segment Offload accesses the TCP header in the packet. If the >+packet is too short we must not attempt to access header fields: >+ >+ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); >+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 5 +++++ >+ 1 file changed, 5 insertions(+) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index ed2b23b..c8f0df9 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2224,6 +2224,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ >+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) >+ { >++ /* Large enough for the TCP header? */ >++ if (ip_data_len < sizeof(tcp_header)) { >++ goto skip_offload; >++ } >++ >+ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; >+ >+ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-6.patch >___________________________________________________________________ >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: files/xsa140-qemuu-unstable-7.patch >=================================================================== >--- files/xsa140-qemuu-unstable-7.patch (revision 0) >+++ files/xsa140-qemuu-unstable-7.patch (working copy) >@@ -0,0 +1,32 @@ >+From 9a084807bf6ca7c16d997a236d304111894a6539 Mon Sep 17 00:00:00 2001 >+From: Stefan Hajnoczi <stefanha@redhat.com> >+Date: Wed, 15 Jul 2015 18:17:04 +0100 >+Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field >+ >+The TCP Data Offset field contains the length of the header. Make sure >+it is valid and does not exceed the IP data length. >+ >+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >+--- >+ hw/net/rtl8139.c | 5 +++++ >+ 1 file changed, 5 insertions(+) >+ >+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c >+index c8f0df9..2df4a51 100644 >+--- a/hw/net/rtl8139.c >++++ b/hw/net/rtl8139.c >+@@ -2253,6 +2253,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) >+ >+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); >+ >++ /* Invalid TCP data offset? */ >++ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) { >++ goto skip_offload; >++ } >++ >+ /* ETH_MTU = ip header len + tcp header len + payload */ >+ int tcp_data_len = ip_data_len - tcp_hlen; >+ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; >+-- >+2.1.4 >+ > >Property changes on: files/xsa140-qemuu-unstable-7.patch >___________________________________________________________________ >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Index: pkg-plist >=================================================================== >--- pkg-plist (revision 394239) >+++ pkg-plist (working copy) >@@ -36,6 +36,7 @@ > include/libxl_json.h > include/libxl_utils.h > include/libxl_uuid.h >+include/libxlutil.h > include/xen/COPYING > include/xen/arch-arm.h > include/xen/arch-arm/hvm/save.h
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 201931
:
159378
|
159379
|
159380
|
159894
| 159897 |
159898