aboutsummaryrefslogtreecommitdiff
path: root/sysutils/xen-tools
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2015-06-11 18:26:45 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2015-06-11 18:26:45 +0000
commit03196bcbc3ea90f9c6c7f64e7d8ae4f158bcd67f (patch)
treef6acc8779f63852063ca0c68590979f8a80f8f2d /sysutils/xen-tools
parentfed01f227f8c879099624d5c534b64209a909d60 (diff)
downloadports-03196bcbc3ea90f9c6c7f64e7d8ae4f158bcd67f.tar.gz
ports-03196bcbc3ea90f9c6c7f64e7d8ae4f158bcd67f.zip
Notes
Diffstat (limited to 'sysutils/xen-tools')
-rw-r--r--sysutils/xen-tools/Makefile14
-rw-r--r--sysutils/xen-tools/files/xsa119-unstable.patch99
-rw-r--r--sysutils/xen-tools/files/xsa125.patch154
-rw-r--r--sysutils/xen-tools/files/xsa126-qemut.patch151
-rw-r--r--sysutils/xen-tools/files/xsa126-qemuu.patch128
-rw-r--r--sysutils/xen-tools/files/xsa128-qemut.patch125
-rw-r--r--sysutils/xen-tools/files/xsa128-qemuu.patch118
-rw-r--r--sysutils/xen-tools/files/xsa129-qemut.patch142
-rw-r--r--sysutils/xen-tools/files/xsa129-qemuu.patch172
-rw-r--r--sysutils/xen-tools/files/xsa130-qemut.patch21
-rw-r--r--sysutils/xen-tools/files/xsa130-qemuu.patch71
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-1.patch60
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-2.patch140
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-3.patch22
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-4.patch266
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-5.patch22
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-6.patch85
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-7.patch81
-rw-r--r--sysutils/xen-tools/files/xsa131-qemut-8.patch139
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-1.patch60
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-2.patch70
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-3.patch22
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-4.patch248
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-5.patch22
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-6.patch75
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-7.patch70
-rw-r--r--sysutils/xen-tools/files/xsa131-qemuu-8.patch122
-rw-r--r--sysutils/xen-tools/files/xsa133-qemut.patch80
-rw-r--r--sysutils/xen-tools/files/xsa133-qemuu.patch84
-rw-r--r--sysutils/xen-tools/files/xsa135-qemut-1.patch92
-rw-r--r--sysutils/xen-tools/files/xsa135-qemut-2.patch45
-rw-r--r--sysutils/xen-tools/files/xsa135-qemuu-4.5-1.patch94
-rw-r--r--sysutils/xen-tools/files/xsa135-qemuu-4.5-2.patch45
33 files changed, 3138 insertions, 1 deletions
diff --git a/sysutils/xen-tools/Makefile b/sysutils/xen-tools/Makefile
index 3ed994e08806..03a24ac23c63 100644
--- a/sysutils/xen-tools/Makefile
+++ b/sysutils/xen-tools/Makefile
@@ -3,7 +3,7 @@
PORTNAME= xen
PKGNAMESUFFIX= -tools
PORTVERSION= 4.5.0
-PORTREVISION= 5
+PORTREVISION= 6
CATEGORIES= sysutils emulators
MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/ \
http://code.coreboot.org/p/seabios/downloads/get/:seabios
@@ -46,6 +46,10 @@ QEMU_ARGS= --disable-gtk \
--disable-tools \
--disable-curl \
--cxx=c++
+
+EXTRA_PATCHES= ${FILESDIR}/xsa119-unstable.patch:-p1 \
+ ${FILESDIR}/xsa125.patch:-p1
+
CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}"
SHEBANG_FILES= tools/misc/xencov_split \
tools/misc/xen-ringwatch
@@ -71,6 +75,14 @@ post-patch:
${WRKSRC}/tools/libxl/libxl_dm.c \
${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \
${WRKSRC}/docs/man/*
+ @for p in ${FILESDIR}/*qemut*.patch; do \
+ ${ECHO_CMD} "====> Applying $${p##*/}" ; \
+ patch -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen-traditional ; \
+ done
+ @for p in ${FILESDIR}/*qemuu*.patch; do \
+ ${ECHO_CMD} "====> Applying $${p##*/}" ; \
+ patch -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \
+ done
post-install:
${MKDIR} ${STAGEDIR}/var/run/xen
diff --git a/sysutils/xen-tools/files/xsa119-unstable.patch b/sysutils/xen-tools/files/xsa119-unstable.patch
new file mode 100644
index 000000000000..f696eb5b6eb6
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa119-unstable.patch
@@ -0,0 +1,99 @@
+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
+
diff --git a/sysutils/xen-tools/files/xsa125.patch b/sysutils/xen-tools/files/xsa125.patch
new file mode 100644
index 000000000000..ad5dbb31c204
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa125.patch
@@ -0,0 +1,154 @@
+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
+
diff --git a/sysutils/xen-tools/files/xsa126-qemut.patch b/sysutils/xen-tools/files/xsa126-qemut.patch
new file mode 100644
index 000000000000..599ff172e485
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa126-qemut.patch
@@ -0,0 +1,151 @@
+xen: limit guest control of PCI command register
+
+Otherwise the guest can abuse that control to cause e.g. PCIe
+Unsupported Request responses (by disabling memory and/or I/O decoding
+and subsequently causing [CPU side] accesses to the respective address
+ranges), which (depending on system configuration) may be fatal to the
+host.
+
+This is CVE-2015-2756 / XSA-126.
+
+Signed-off-by: Jan Beulich <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");
diff --git a/sysutils/xen-tools/files/xsa126-qemuu.patch b/sysutils/xen-tools/files/xsa126-qemuu.patch
new file mode 100644
index 000000000000..21805a43be51
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa126-qemuu.patch
@@ -0,0 +1,128 @@
+xen: limit guest control of PCI command register
+
+Otherwise the guest can abuse that control to cause e.g. PCIe
+Unsupported Request responses (by disabling memory and/or I/O decoding
+and subsequently causing [CPU side] accesses to the respective address
+ranges), which (depending on system configuration) may be fatal to the
+host.
+
+This is CVE-2015-2756 / XSA-126.
+
+Signed-off-by: Jan Beulich <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 */
diff --git a/sysutils/xen-tools/files/xsa128-qemut.patch b/sysutils/xen-tools/files/xsa128-qemut.patch
new file mode 100644
index 000000000000..7530690bdfc4
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa128-qemut.patch
@@ -0,0 +1,125 @@
+xen: properly gate host writes of modified PCI CFG contents
+
+The old logic didn't work as intended when an access spanned multiple
+fields (for example a 32-bit access to the location of the MSI Message
+Data field with the high 16 bits not being covered by any known field).
+Remove it and derive which fields not to write to from the accessed
+fields' emulation masks: When they're all ones, there's no point in
+doing any host write.
+
+This fixes a secondary issue at once: We obviously shouldn't make any
+host write attempt when already the host read failed.
+
+This is XSA-128.
+
+Signed-off-by: Jan Beulich <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 {
diff --git a/sysutils/xen-tools/files/xsa128-qemuu.patch b/sysutils/xen-tools/files/xsa128-qemuu.patch
new file mode 100644
index 000000000000..d551c6244a76
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa128-qemuu.patch
@@ -0,0 +1,118 @@
+xen: properly gate host writes of modified PCI CFG contents
+
+The old logic didn't work as intended when an access spanned multiple
+fields (for example a 32-bit access to the location of the MSI Message
+Data field with the high 16 bits not being covered by any known field).
+Remove it and derive which fields not to write to from the accessed
+fields' emulation masks: When they're all ones, there's no point in
+doing any host write.
+
+This fixes a secondary issue at once: We obviously shouldn't make any
+host write attempt when already the host read failed.
+
+This is XSA-128.
+
+Signed-off-by: Jan Beulich <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,
diff --git a/sysutils/xen-tools/files/xsa129-qemut.patch b/sysutils/xen-tools/files/xsa129-qemut.patch
new file mode 100644
index 000000000000..005efa5dd83d
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa129-qemut.patch
@@ -0,0 +1,142 @@
+xen: don't allow guest to control MSI mask register
+
+It's being used by the hypervisor. For now simply mimic a device not
+capable of masking, and fully emulate any accesses a guest may issue
+nevertheless as simple reads/writes without side effects.
+
+This is XSA-129.
+
+Signed-off-by: Jan Beulich <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
diff --git a/sysutils/xen-tools/files/xsa129-qemuu.patch b/sysutils/xen-tools/files/xsa129-qemuu.patch
new file mode 100644
index 000000000000..96715a68d372
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa129-qemuu.patch
@@ -0,0 +1,172 @@
+xen: don't allow guest to control MSI mask register
+
+It's being used by the hypervisor. For now simply mimic a device not
+capable of masking, and fully emulate any accesses a guest may issue
+nevertheless as simple reads/writes without side effects.
+
+This is XSA-129.
+
+Signed-off-by: Jan Beulich <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
diff --git a/sysutils/xen-tools/files/xsa130-qemut.patch b/sysutils/xen-tools/files/xsa130-qemut.patch
new file mode 100644
index 000000000000..75af778b0172
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa130-qemut.patch
@@ -0,0 +1,21 @@
+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)
diff --git a/sysutils/xen-tools/files/xsa130-qemuu.patch b/sysutils/xen-tools/files/xsa130-qemuu.patch
new file mode 100644
index 000000000000..c2f35bd0b902
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa130-qemuu.patch
@@ -0,0 +1,71 @@
+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;
+ }
+
diff --git a/sysutils/xen-tools/files/xsa131-qemut-1.patch b/sysutils/xen-tools/files/xsa131-qemut-1.patch
new file mode 100644
index 000000000000..3bfe23698261
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-1.patch
@@ -0,0 +1,60 @@
+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;
+ }
+
diff --git a/sysutils/xen-tools/files/xsa131-qemut-2.patch b/sysutils/xen-tools/files/xsa131-qemut-2.patch
new file mode 100644
index 000000000000..cb2c7b9b2094
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-2.patch
@@ -0,0 +1,140 @@
+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)
diff --git a/sysutils/xen-tools/files/xsa131-qemut-3.patch b/sysutils/xen-tools/files/xsa131-qemut-3.patch
new file mode 100644
index 000000000000..a50b2392b7ac
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-3.patch
@@ -0,0 +1,22 @@
+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;
diff --git a/sysutils/xen-tools/files/xsa131-qemut-4.patch b/sysutils/xen-tools/files/xsa131-qemut-4.patch
new file mode 100644
index 000000000000..95a7f517003f
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-4.patch
@@ -0,0 +1,266 @@
+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 */
diff --git a/sysutils/xen-tools/files/xsa131-qemut-5.patch b/sysutils/xen-tools/files/xsa131-qemut-5.patch
new file mode 100644
index 000000000000..fb5c4d403d8d
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-5.patch
@@ -0,0 +1,22 @@
+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,
diff --git a/sysutils/xen-tools/files/xsa131-qemut-6.patch b/sysutils/xen-tools/files/xsa131-qemut-6.patch
new file mode 100644
index 000000000000..02d175d424e8
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-6.patch
@@ -0,0 +1,85 @@
+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) */
diff --git a/sysutils/xen-tools/files/xsa131-qemut-7.patch b/sysutils/xen-tools/files/xsa131-qemut-7.patch
new file mode 100644
index 000000000000..b2430b5143a1
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-7.patch
@@ -0,0 +1,81 @@
+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
diff --git a/sysutils/xen-tools/files/xsa131-qemut-8.patch b/sysutils/xen-tools/files/xsa131-qemut-8.patch
new file mode 100644
index 000000000000..875ae9646f56
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemut-8.patch
@@ -0,0 +1,139 @@
+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)
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-1.patch b/sysutils/xen-tools/files/xsa131-qemuu-1.patch
new file mode 100644
index 000000000000..ece230bb381d
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-1.patch
@@ -0,0 +1,60 @@
+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,
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-2.patch b/sysutils/xen-tools/files/xsa131-qemuu-2.patch
new file mode 100644
index 000000000000..fc547f493e10
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-2.patch
@@ -0,0 +1,70 @@
+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,
+ },
+ {
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-3.patch b/sysutils/xen-tools/files/xsa131-qemuu-3.patch
new file mode 100644
index 000000000000..f62a4f804503
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-3.patch
@@ -0,0 +1,22 @@
+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;
+ }
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-4.patch b/sysutils/xen-tools/files/xsa131-qemuu-4.patch
new file mode 100644
index 000000000000..c36669beeebf
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-4.patch
@@ -0,0 +1,248 @@
+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 */
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-5.patch b/sysutils/xen-tools/files/xsa131-qemuu-5.patch
new file mode 100644
index 000000000000..aed87c638a95
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-5.patch
@@ -0,0 +1,22 @@
+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,
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-6.patch b/sysutils/xen-tools/files/xsa131-qemuu-6.patch
new file mode 100644
index 000000000000..98313d07275c
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-6.patch
@@ -0,0 +1,75 @@
+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,
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-7.patch b/sysutils/xen-tools/files/xsa131-qemuu-7.patch
new file mode 100644
index 000000000000..fa27fec84479
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-7.patch
@@ -0,0 +1,70 @@
+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,
diff --git a/sysutils/xen-tools/files/xsa131-qemuu-8.patch b/sysutils/xen-tools/files/xsa131-qemuu-8.patch
new file mode 100644
index 000000000000..9537baf27d50
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa131-qemuu-8.patch
@@ -0,0 +1,122 @@
+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;
+ }
+
diff --git a/sysutils/xen-tools/files/xsa133-qemut.patch b/sysutils/xen-tools/files/xsa133-qemut.patch
new file mode 100644
index 000000000000..e1b77117df16
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa133-qemut.patch
@@ -0,0 +1,80 @@
+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
diff --git a/sysutils/xen-tools/files/xsa133-qemuu.patch b/sysutils/xen-tools/files/xsa133-qemuu.patch
new file mode 100644
index 000000000000..95f3dcc21e5b
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa133-qemuu.patch
@@ -0,0 +1,84 @@
+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
+
+
diff --git a/sysutils/xen-tools/files/xsa135-qemut-1.patch b/sysutils/xen-tools/files/xsa135-qemut-1.patch
new file mode 100644
index 000000000000..1102ce67fc3e
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa135-qemut-1.patch
@@ -0,0 +1,92 @@
+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/pcnet.c b/hw/pcnet.c
+index 7cc0637..9f3e1cc 100644
+--- a/hw/pcnet.c
++++ b/hw/pcnet.c
+@@ -1250,7 +1250,7 @@ static void pcnet_transmit(PCNetState *s)
+ target_phys_addr_t xmit_cxda = 0;
+ int count = CSR_XMTRL(s)-1;
+ int add_crc = 0;
+-
++ int bcnt;
+ s->xmit_pos = -1;
+
+ if (!CSR_TXON(s)) {
+@@ -1276,34 +1276,39 @@ static void pcnet_transmit(PCNetState *s)
+ if (BCR_SWSTYLE(s) != 1)
+ add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
+ }
++
++ 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(s, s->buffer, s->xmit_pos);
+- s->looptest = 0;
+- } else
+- if (s->vc)
+- qemu_send_packet(s->vc, 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(s, s->buffer, s->xmit_pos);
++ s->looptest = 0;
++ } else {
++ if (s->vc) {
++ qemu_send_packet(s->vc, 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)));
+ if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
diff --git a/sysutils/xen-tools/files/xsa135-qemut-2.patch b/sysutils/xen-tools/files/xsa135-qemut-2.patch
new file mode 100644
index 000000000000..bc3d02f30f5f
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa135-qemut-2.patch
@@ -0,0 +1,45 @@
+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/pcnet.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/hw/pcnet.c b/hw/pcnet.c
+index bdfd38f..6d32e4c 100644
+--- a/hw/pcnet.c
++++ b/hw/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
+
diff --git a/sysutils/xen-tools/files/xsa135-qemuu-4.5-1.patch b/sysutils/xen-tools/files/xsa135-qemuu-4.5-1.patch
new file mode 100644
index 000000000000..31b161026f14
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa135-qemuu-4.5-1.patch
@@ -0,0 +1,94 @@
+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)));
diff --git a/sysutils/xen-tools/files/xsa135-qemuu-4.5-2.patch b/sysutils/xen-tools/files/xsa135-qemuu-4.5-2.patch
new file mode 100644
index 000000000000..4fe7df5440fd
--- /dev/null
+++ b/sysutils/xen-tools/files/xsa135-qemuu-4.5-2.patch
@@ -0,0 +1,45 @@
+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
+