gnu: qemu: Update to 2.4.0.1. Include fix for CVE-2015-6855.
* gnu/packages/patches/qemu-CVE-2015-3209.patch, gnu/packages/patches/qemu-CVE-2015-4037.patch, gnu/packages/patches/qemu-CVE-2015-4103.patch, gnu/packages/patches/qemu-CVE-2015-4104.patch, gnu/packages/patches/qemu-CVE-2015-4105.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt1.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt2.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt3.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt4.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt5.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt6.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt7.patch, gnu/packages/patches/qemu-CVE-2015-4106-pt8.patch, gnu/packages/patches/qemu-CVE-2015-5745.patch: Delete files. * gnu/packages/patches/qemu-CVE-2015-6855.patch: New file. * gnu-system.am (dist_patch_DATA): Add the new patch and delete the old ones. * gnu/packages/qemu.scm (qemu-headless): Update to 2.4.0.1. Add the new patch and delete the old ones.
This commit is contained in:
		
							parent
							
								
									e1556533d3
								
							
						
					
					
						commit
						d2a6336609
					
				
					 17 changed files with 148 additions and 1345 deletions
				
			
		| 
						 | 
					@ -607,20 +607,7 @@ dist_patch_DATA =						\
 | 
				
			||||||
  gnu/packages/patches/python-fix-tests.patch			\
 | 
					  gnu/packages/patches/python-fix-tests.patch			\
 | 
				
			||||||
  gnu/packages/patches/python2-rdflib-drop-sparqlwrapper.patch	\
 | 
					  gnu/packages/patches/python2-rdflib-drop-sparqlwrapper.patch	\
 | 
				
			||||||
  gnu/packages/patches/python2-pygobject-2-gi-info-type-error-domain.patch \
 | 
					  gnu/packages/patches/python2-pygobject-2-gi-info-type-error-domain.patch \
 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-3209.patch			\
 | 
					  gnu/packages/patches/qemu-CVE-2015-6855.patch			\
 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4037.patch			\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4103.patch			\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4104.patch			\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4105.patch			\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt1.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt2.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt3.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt4.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt5.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt6.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt7.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-4106-pt8.patch		\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qemu-CVE-2015-5745.patch			\
 | 
					 | 
				
			||||||
  gnu/packages/patches/qt4-ldflags.patch			\
 | 
					  gnu/packages/patches/qt4-ldflags.patch			\
 | 
				
			||||||
  gnu/packages/patches/qt4-tests.patch				\
 | 
					  gnu/packages/patches/qt4-tests.patch				\
 | 
				
			||||||
  gnu/packages/patches/qt5-runpath.patch			\
 | 
					  gnu/packages/patches/qt5-runpath.patch			\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,49 +0,0 @@
 | 
				
			||||||
From 9f7c594c006289ad41169b854d70f5da6e400a2a 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Fixed 3-space indentation to QEMU's 4-space coding standard.
 | 
					 | 
				
			||||||
--Stefan]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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>
 | 
					 | 
				
			||||||
Signed-off-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..68b9981 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.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,53 +0,0 @@
 | 
				
			||||||
From 8b8f1c7e9ddb2e88a144638f6527bf70e32343e3 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Michael Tokarev <mjt@tls.msk.ru>
 | 
					 | 
				
			||||||
Date: Thu, 28 May 2015 14:12:26 +0300
 | 
					 | 
				
			||||||
Subject: [PATCH] slirp: use less predictable directory name in /tmp for smb
 | 
					 | 
				
			||||||
 config (CVE-2015-4037)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In this version I used mkdtemp(3) which is:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _BSD_SOURCE
 | 
					 | 
				
			||||||
        || /* Since glibc 2.10: */
 | 
					 | 
				
			||||||
            (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
(POSIX.1-2008), so should be available on systems we care about.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
While at it, reset the resulting directory name within smb structure
 | 
					 | 
				
			||||||
on error so cleanup function wont try to remove directory which we
 | 
					 | 
				
			||||||
failed to create.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
 | 
					 | 
				
			||||||
Reviewed-by: Markus Armbruster <armbru@redhat.com>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 net/slirp.c | 7 +++----
 | 
					 | 
				
			||||||
 1 file changed, 3 insertions(+), 4 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/net/slirp.c b/net/slirp.c
 | 
					 | 
				
			||||||
index 0e15cf6..3533837 100644
 | 
					 | 
				
			||||||
--- a/net/slirp.c
 | 
					 | 
				
			||||||
+++ b/net/slirp.c
 | 
					 | 
				
			||||||
@@ -481,7 +481,6 @@ static void slirp_smb_cleanup(SlirpState *s)
 | 
					 | 
				
			||||||
 static int slirp_smb(SlirpState* s, const char *exported_dir,
 | 
					 | 
				
			||||||
                      struct in_addr vserver_addr)
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
-    static int instance;
 | 
					 | 
				
			||||||
     char smb_conf[128];
 | 
					 | 
				
			||||||
     char smb_cmdline[128];
 | 
					 | 
				
			||||||
     struct passwd *passwd;
 | 
					 | 
				
			||||||
@@ -505,10 +504,10 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
 | 
					 | 
				
			||||||
         return -1;
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-    snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
 | 
					 | 
				
			||||||
-             (long)getpid(), instance++);
 | 
					 | 
				
			||||||
-    if (mkdir(s->smb_dir, 0700) < 0) {
 | 
					 | 
				
			||||||
+    snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.XXXXXX");
 | 
					 | 
				
			||||||
+    if (!mkdtemp(s->smb_dir)) {
 | 
					 | 
				
			||||||
         error_report("could not create samba server dir '%s'", s->smb_dir);
 | 
					 | 
				
			||||||
+        s->smb_dir[0] = 0;
 | 
					 | 
				
			||||||
         return -1;
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
     snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,135 +0,0 @@
 | 
				
			||||||
From 5c83b2f5b4b956e91dd6e5711f14df7ab800aefb Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:00 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.c             | 25 +++++++++++++++++++++----
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.h             |  2 --
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c |  4 ----
 | 
					 | 
				
			||||||
 3 files changed, 21 insertions(+), 10 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
index d095c08..8923582 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
@@ -234,7 +234,7 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
     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(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
     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(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
             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(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
     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);
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
 | 
					 | 
				
			||||||
index 942dc60..52ceb85 100644
 | 
					 | 
				
			||||||
--- 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 */
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 95a51db..dae0519 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -1279,7 +1279,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,
 | 
					 | 
				
			||||||
@@ -1291,7 +1290,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,
 | 
					 | 
				
			||||||
@@ -1303,7 +1301,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,
 | 
					 | 
				
			||||||
@@ -1315,7 +1312,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,
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,189 +0,0 @@
 | 
				
			||||||
From 7611dae8a69f0f1775ba1a9a942961c2aa10d88e Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:00 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/pci/msi.c                |  4 --
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 98 ++++++++++++++++++++++++++++++++++++++++-----
 | 
					 | 
				
			||||||
 include/hw/pci/pci_regs.h   |  2 +
 | 
					 | 
				
			||||||
 3 files changed, 90 insertions(+), 14 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
 | 
					 | 
				
			||||||
index c111dba..f9c0484 100644
 | 
					 | 
				
			||||||
--- 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)
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index dae0519..68b8f22 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -1016,13 +1016,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,
 | 
					 | 
				
			||||||
@@ -1134,7 +1130,45 @@ static int xen_pt_msgdata_reg_init(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -1222,7 +1256,7 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -1267,7 +1301,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,
 | 
					 | 
				
			||||||
@@ -1316,6 +1350,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,
 | 
					 | 
				
			||||||
     },
 | 
					 | 
				
			||||||
diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
 | 
					 | 
				
			||||||
index 56a404b..57e8c80 100644
 | 
					 | 
				
			||||||
--- 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
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,85 +0,0 @@
 | 
				
			||||||
From b38ec5ee7a581776bbce0bdaecb397632c3c4791 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:00 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] xen/MSI-X: limit error messages
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.h     |  1 +
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_msi.c | 12 +++++++-----
 | 
					 | 
				
			||||||
 2 files changed, 8 insertions(+), 5 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
 | 
					 | 
				
			||||||
index 52ceb85..8c9b6c2 100644
 | 
					 | 
				
			||||||
--- 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;
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c
 | 
					 | 
				
			||||||
index 9ed9321..68db623 100644
 | 
					 | 
				
			||||||
--- 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, hwaddr addr,
 | 
					 | 
				
			||||||
     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, hwaddr addr,
 | 
					 | 
				
			||||||
             + 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;
 | 
					 | 
				
			||||||
         }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,72 +0,0 @@
 | 
				
			||||||
From d1d35cf4ffb6a60a356193397919e83306d0bb74 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 10 ++--------
 | 
					 | 
				
			||||||
 1 file changed, 2 insertions(+), 8 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 68b8f22..436d0fd 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -1053,7 +1053,6 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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) {
 | 
					 | 
				
			||||||
@@ -1066,12 +1065,11 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -1099,10 +1097,6 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
         xen_pt_msi_disable(s);
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-    /* pass through MSI_ENABLE bit */
 | 
					 | 
				
			||||||
-    *val &= ~PCI_MSI_FLAGS_ENABLE;
 | 
					 | 
				
			||||||
-    *val |= raw_val & PCI_MSI_FLAGS_ENABLE;
 | 
					 | 
				
			||||||
-
 | 
					 | 
				
			||||||
     return 0;
 | 
					 | 
				
			||||||
 }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
@@ -1301,7 +1295,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,
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,81 +0,0 @@
 | 
				
			||||||
From d61bb2482dc0c7426f451f23ba7e2748ae2cc06d Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 25 ++++---------------------
 | 
					 | 
				
			||||||
 1 file changed, 4 insertions(+), 21 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 436d0fd..516236a 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -933,38 +933,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;
 | 
					 | 
				
			||||||
@@ -1000,9 +983,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,
 | 
					 | 
				
			||||||
     },
 | 
					 | 
				
			||||||
     {
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,33 +0,0 @@
 | 
				
			||||||
From c4ff1e68c621928abc680266cad0a451686c403b Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 3 ++-
 | 
					 | 
				
			||||||
 1 file changed, 2 insertions(+), 1 deletion(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 516236a..027ac32 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -948,7 +948,8 @@ static int xen_pt_pmcsr_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
     /* 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;
 | 
					 | 
				
			||||||
 }
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,260 +0,0 @@
 | 
				
			||||||
From 0e7ef22136955169a0fd03c4e41af95662352733 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 51 ++++++++++++++++++---------------------------
 | 
					 | 
				
			||||||
 1 file changed, 20 insertions(+), 31 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 027ac32..3833b9e 100644
 | 
					 | 
				
			||||||
--- 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 *reg_grp, uint32_t address)
 | 
					 | 
				
			||||||
     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(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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 {
 | 
					 | 
				
			||||||
@@ -454,7 +457,6 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -511,8 +513,7 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
     /* 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;
 | 
					 | 
				
			||||||
 }
 | 
					 | 
				
			||||||
@@ -526,9 +527,8 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -537,7 +537,6 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -545,7 +544,6 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -940,14 +938,13 @@ static int xen_pt_pmcsr_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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);
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
@@ -1036,7 +1033,7 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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) {
 | 
					 | 
				
			||||||
@@ -1049,7 +1046,6 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -1161,7 +1157,6 @@ static int xen_pt_msgaddr32_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -1170,8 +1165,7 @@ static int xen_pt_msgaddr32_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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) {
 | 
					 | 
				
			||||||
@@ -1189,7 +1183,6 @@ static int xen_pt_msgaddr64_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -1206,8 +1199,7 @@ static int xen_pt_msgaddr64_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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) {
 | 
					 | 
				
			||||||
@@ -1229,7 +1221,6 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
@@ -1247,8 +1238,7 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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) {
 | 
					 | 
				
			||||||
@@ -1410,7 +1400,7 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
@@ -1418,7 +1408,6 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
     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 */
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,33 +0,0 @@
 | 
				
			||||||
From 45ebe3916ab16f859ed930e92fbd52d84d5dcdaf Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 2 +-
 | 
					 | 
				
			||||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 3833b9e..9f6c00e 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -871,7 +871,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,
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,89 +0,0 @@
 | 
				
			||||||
From 0ad3393ad032f76e88b4dbd04d36ad84dff75dd6 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.h             |  2 ++
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 14 +++++++++-----
 | 
					 | 
				
			||||||
 2 files changed, 11 insertions(+), 5 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
 | 
					 | 
				
			||||||
index 8c9b6c2..f9795eb 100644
 | 
					 | 
				
			||||||
--- 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) */
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 9f6c00e..efd8bac 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -578,7 +578,7 @@ static XenPTRegInfo xen_pt_emu_reg_header0[] = {
 | 
					 | 
				
			||||||
         .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,
 | 
					 | 
				
			||||||
@@ -603,7 +603,8 @@ static XenPTRegInfo xen_pt_emu_reg_header0[] = {
 | 
					 | 
				
			||||||
         .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,
 | 
					 | 
				
			||||||
@@ -980,7 +981,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,
 | 
					 | 
				
			||||||
@@ -1268,7 +1270,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,
 | 
					 | 
				
			||||||
@@ -1446,7 +1449,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,
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,72 +0,0 @@
 | 
				
			||||||
From a88a3f887181605f4487a22bdfb7d87ffafde5d9 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c | 28 ++++++++++++++++++++++++++++
 | 
					 | 
				
			||||||
 1 file changed, 28 insertions(+)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index efd8bac..19f926b 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
@@ -754,6 +754,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,
 | 
					 | 
				
			||||||
     },
 | 
					 | 
				
			||||||
 };
 | 
					 | 
				
			||||||
@@ -889,6 +898,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,
 | 
					 | 
				
			||||||
@@ -900,6 +919,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,
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,132 +0,0 @@
 | 
				
			||||||
From c25bbf1545a53ac051f9e51d4140e397660c10ae Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: Jan Beulich <jbeulich@suse.com>
 | 
					 | 
				
			||||||
Date: Tue, 2 Jun 2015 15:07:01 +0000
 | 
					 | 
				
			||||||
Subject: [PATCH] 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>)
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.c             | 32 +++++++++++++++++++++++++++++---
 | 
					 | 
				
			||||||
 hw/xen/xen_pt.h             |  2 ++
 | 
					 | 
				
			||||||
 hw/xen/xen_pt_config_init.c |  4 ++++
 | 
					 | 
				
			||||||
 3 files changed, 35 insertions(+), 3 deletions(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
index 8923582..9afcda8 100644
 | 
					 | 
				
			||||||
--- a/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
+++ b/hw/xen/xen_pt.c
 | 
					 | 
				
			||||||
@@ -239,6 +239,7 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
     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;
 | 
					 | 
				
			||||||
@@ -278,6 +279,10 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
     /* 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;
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
@@ -298,12 +303,15 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
             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));
 | 
					 | 
				
			||||||
             }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
@@ -347,6 +355,16 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
         } 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++;
 | 
					 | 
				
			||||||
         }
 | 
					 | 
				
			||||||
@@ -358,6 +376,13 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
 | 
					 | 
				
			||||||
     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)) {
 | 
					 | 
				
			||||||
@@ -824,6 +849,7 @@ static void xen_pt_unregister_device(PCIDevice *d)
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
 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(),
 | 
					 | 
				
			||||||
 };
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
 | 
					 | 
				
			||||||
index f9795eb..4bba559 100644
 | 
					 | 
				
			||||||
--- 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;
 | 
					 | 
				
			||||||
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
 | 
					 | 
				
			||||||
index 19f926b..f3cf069 100644
 | 
					 | 
				
			||||||
--- 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(const XenPCIPassthroughState *s,
 | 
					 | 
				
			||||||
 {
 | 
					 | 
				
			||||||
     uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask);
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
+    if (!s->permissive) {
 | 
					 | 
				
			||||||
+        throughable_mask &= ~reg->res_mask;
 | 
					 | 
				
			||||||
+    }
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
     return throughable_mask & valid_mask;
 | 
					 | 
				
			||||||
 }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,32 +0,0 @@
 | 
				
			||||||
From 7882080388be5088e72c425b02223c02e6cb4295 Mon Sep 17 00:00:00 2001
 | 
					 | 
				
			||||||
From: "Michael S. Tsirkin" <mst@redhat.com>
 | 
					 | 
				
			||||||
Date: Thu, 23 Jul 2015 17:52:02 +0300
 | 
					 | 
				
			||||||
Subject: [PATCH] virtio-serial: fix ANY_LAYOUT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Don't assume a specific layout for control messages.
 | 
					 | 
				
			||||||
Required by virtio 1.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 | 
					 | 
				
			||||||
Reviewed-by: Amit Shah <amit.shah@redhat.com>
 | 
					 | 
				
			||||||
Reviewed-by: Jason Wang <jasowang@redhat.com>
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 hw/char/virtio-serial-bus.c | 3 ++-
 | 
					 | 
				
			||||||
 1 file changed, 2 insertions(+), 1 deletion(-)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
 | 
					 | 
				
			||||||
index 78c73e5..929e49c 100644
 | 
					 | 
				
			||||||
--- a/hw/char/virtio-serial-bus.c
 | 
					 | 
				
			||||||
+++ b/hw/char/virtio-serial-bus.c
 | 
					 | 
				
			||||||
@@ -195,7 +195,8 @@ static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
 | 
					 | 
				
			||||||
         return 0;
 | 
					 | 
				
			||||||
     }
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
-    memcpy(elem.in_sg[0].iov_base, buf, len);
 | 
					 | 
				
			||||||
+    /* TODO: detect a buffer that's too short, set NEEDS_RESET */
 | 
					 | 
				
			||||||
+    iov_from_buf(elem.in_sg, elem.in_num, 0, buf, len);
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
     virtqueue_push(vq, &elem, len);
 | 
					 | 
				
			||||||
     virtio_notify(VIRTIO_DEVICE(vser), vq);
 | 
					 | 
				
			||||||
-- 
 | 
					 | 
				
			||||||
2.4.3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										144
									
								
								gnu/packages/patches/qemu-CVE-2015-6855.patch
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								gnu/packages/patches/qemu-CVE-2015-6855.patch
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,144 @@
 | 
				
			||||||
 | 
					From d9033e1d3aa666c5071580617a57bd853c5d794a Mon Sep 17 00:00:00 2001
 | 
				
			||||||
 | 
					From: John Snow <jsnow@redhat.com>
 | 
				
			||||||
 | 
					Date: Thu, 17 Sep 2015 14:17:05 -0400
 | 
				
			||||||
 | 
					Subject: [PATCH] ide: fix ATAPI command permissions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We're a little too lenient with what we'll let an ATAPI drive handle.
 | 
				
			||||||
 | 
					Clamp down on the IDE command execution table to remove CD_OK permissions
 | 
				
			||||||
 | 
					from commands that are not and have never been ATAPI commands.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For ATAPI command validity, please see:
 | 
				
			||||||
 | 
					- ATA4 Section 6.5 ("PACKET Command feature set")
 | 
				
			||||||
 | 
					- ATA8/ACS Section 4.3 ("The PACKET feature set")
 | 
				
			||||||
 | 
					- ACS3 Section 4.3 ("The PACKET feature set")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACS3 has a historical command validity table in Table B.4
 | 
				
			||||||
 | 
					("Historical Command Assignments") that can be referenced to find when
 | 
				
			||||||
 | 
					a command was introduced, deprecated, obsoleted, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The only reference for ATAPI command validity is by checking that
 | 
				
			||||||
 | 
					version's PACKET feature set section.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ATAPI was introduced by T13 into ATA4, all commands retired prior to ATA4
 | 
				
			||||||
 | 
					therefore are assumed to have never been ATAPI commands.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mandatory commands, as listed in ATA8-ACS3, are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- DEVICE RESET
 | 
				
			||||||
 | 
					- EXECUTE DEVICE DIAGNOSTIC
 | 
				
			||||||
 | 
					- IDENTIFY DEVICE
 | 
				
			||||||
 | 
					- IDENTIFY PACKET DEVICE
 | 
				
			||||||
 | 
					- NOP
 | 
				
			||||||
 | 
					- PACKET
 | 
				
			||||||
 | 
					- READ SECTOR(S)
 | 
				
			||||||
 | 
					- SET FEATURES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional commands as listed in ATA8-ACS3, are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- FLUSH CACHE
 | 
				
			||||||
 | 
					- READ LOG DMA EXT
 | 
				
			||||||
 | 
					- READ LOG EXT
 | 
				
			||||||
 | 
					- WRITE LOG DMA EXT
 | 
				
			||||||
 | 
					- WRITE LOG EXT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All other commands are illegal to send to an ATAPI device and should
 | 
				
			||||||
 | 
					be rejected by the device.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CD_OK removal justifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					0x06 WIN_DSM              Defined in ACS2. Not valid for ATAPI.
 | 
				
			||||||
 | 
					0x21 WIN_READ_ONCE        Retired in ATA5. Not ATAPI in ATA4.
 | 
				
			||||||
 | 
					0x94 WIN_STANDBYNOW2      Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0x95 WIN_IDLEIMMEDIATE2   Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0x96 WIN_STANDBY2         Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0x97 WIN_SETIDLE2         Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0x98 WIN_CHECKPOWERMODE2  Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0x99 WIN_SLEEPNOW2        Retired in ATA4. Did not coexist with ATAPI.
 | 
				
			||||||
 | 
					0xE0 WIN_STANDBYNOW1      Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xE1 WIN_IDLEIMMDIATE     Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xE2 WIN_STANDBY          Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xE3 WIN_SETIDLE1         Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xE4 WIN_CHECKPOWERMODE1  Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xE5 WIN_SLEEPNOW1        Not part of ATAPI in ATA4, ACS or ACS3.
 | 
				
			||||||
 | 
					0xF8 WIN_READ_NATIVE_MAX  Obsoleted in ACS3. Not ATAPI in ATA4 or ACS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This patch fixes a divide by zero fault that can be caused by sending
 | 
				
			||||||
 | 
					the WIN_READ_NATIVE_MAX command to an ATAPI drive, which causes it to
 | 
				
			||||||
 | 
					attempt to use zeroed CHS values to perform sector arithmetic.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Reported-by: Qinghao Tang <luodalongde@gmail.com>
 | 
				
			||||||
 | 
					Signed-off-by: John Snow <jsnow@redhat.com>
 | 
				
			||||||
 | 
					Reviewed-by: Markus Armbruster <armbru@redhat.com>
 | 
				
			||||||
 | 
					Message-id: 1441816082-21031-1-git-send-email-jsnow@redhat.com
 | 
				
			||||||
 | 
					CC: qemu-stable@nongnu.org
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 hw/ide/core.c | 30 +++++++++++++++---------------
 | 
				
			||||||
 | 
					 1 file changed, 15 insertions(+), 15 deletions(-)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					diff --git a/hw/ide/core.c b/hw/ide/core.c
 | 
				
			||||||
 | 
					index 8ba04df..1cc6945 100644
 | 
				
			||||||
 | 
					--- a/hw/ide/core.c
 | 
				
			||||||
 | 
					+++ b/hw/ide/core.c
 | 
				
			||||||
 | 
					@@ -1746,11 +1746,11 @@ static const struct {
 | 
				
			||||||
 | 
					 } ide_cmd_table[0x100] = {
 | 
				
			||||||
 | 
					     /* NOP not implemented, mandatory for CD */
 | 
				
			||||||
 | 
					     [CFA_REQ_EXT_ERROR_CODE]      = { cmd_cfa_req_ext_error_code, CFA_OK },
 | 
				
			||||||
 | 
					-    [WIN_DSM]                     = { cmd_data_set_management, ALL_OK },
 | 
				
			||||||
 | 
					+    [WIN_DSM]                     = { cmd_data_set_management, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_DEVICE_RESET]            = { cmd_device_reset, CD_OK },
 | 
				
			||||||
 | 
					     [WIN_RECAL]                   = { cmd_nop, HD_CFA_OK | SET_DSC},
 | 
				
			||||||
 | 
					     [WIN_READ]                    = { cmd_read_pio, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_READ_ONCE]               = { cmd_read_pio, ALL_OK },
 | 
				
			||||||
 | 
					+    [WIN_READ_ONCE]               = { cmd_read_pio, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_READ_EXT]                = { cmd_read_pio, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_READDMA_EXT]             = { cmd_read_dma, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_READ_NATIVE_MAX_EXT]     = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					@@ -1769,12 +1769,12 @@ static const struct {
 | 
				
			||||||
 | 
					     [CFA_TRANSLATE_SECTOR]        = { cmd_cfa_translate_sector, CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_DIAGNOSE]                = { cmd_exec_dev_diagnostic, ALL_OK },
 | 
				
			||||||
 | 
					     [WIN_SPECIFY]                 = { cmd_nop, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					-    [WIN_STANDBYNOW2]             = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_IDLEIMMEDIATE2]          = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_STANDBY2]                = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_SETIDLE2]                = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_CHECKPOWERMODE2]         = { cmd_check_power_mode, ALL_OK | SET_DSC },
 | 
				
			||||||
 | 
					-    [WIN_SLEEPNOW2]               = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					+    [WIN_STANDBYNOW2]             = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_IDLEIMMEDIATE2]          = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_STANDBY2]                = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_SETIDLE2]                = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_CHECKPOWERMODE2]         = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					+    [WIN_SLEEPNOW2]               = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_PACKETCMD]               = { cmd_packet, CD_OK },
 | 
				
			||||||
 | 
					     [WIN_PIDENTIFY]               = { cmd_identify_packet, CD_OK },
 | 
				
			||||||
 | 
					     [WIN_SMART]                   = { cmd_smart, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					@@ -1788,19 +1788,19 @@ static const struct {
 | 
				
			||||||
 | 
					     [WIN_WRITEDMA]                = { cmd_write_dma, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_WRITEDMA_ONCE]           = { cmd_write_dma, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [CFA_WRITE_MULTI_WO_ERASE]    = { cmd_write_multiple, CFA_OK },
 | 
				
			||||||
 | 
					-    [WIN_STANDBYNOW1]             = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_IDLEIMMEDIATE]           = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_STANDBY]                 = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_SETIDLE1]                = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					-    [WIN_CHECKPOWERMODE1]         = { cmd_check_power_mode, ALL_OK | SET_DSC },
 | 
				
			||||||
 | 
					-    [WIN_SLEEPNOW1]               = { cmd_nop, ALL_OK },
 | 
				
			||||||
 | 
					+    [WIN_STANDBYNOW1]             = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_IDLEIMMEDIATE]           = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_STANDBY]                 = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_SETIDLE1]                = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					+    [WIN_CHECKPOWERMODE1]         = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					+    [WIN_SLEEPNOW1]               = { cmd_nop, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_FLUSH_CACHE]             = { cmd_flush_cache, ALL_OK },
 | 
				
			||||||
 | 
					     [WIN_FLUSH_CACHE_EXT]         = { cmd_flush_cache, HD_CFA_OK },
 | 
				
			||||||
 | 
					     [WIN_IDENTIFY]                = { cmd_identify, ALL_OK },
 | 
				
			||||||
 | 
					     [WIN_SETFEATURES]             = { cmd_set_features, ALL_OK | SET_DSC },
 | 
				
			||||||
 | 
					     [IBM_SENSE_CONDITION]         = { cmd_ibm_sense_condition, CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					     [CFA_WEAR_LEVEL]              = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					-    [WIN_READ_NATIVE_MAX]         = { cmd_read_native_max, ALL_OK | SET_DSC },
 | 
				
			||||||
 | 
					+    [WIN_READ_NATIVE_MAX]         = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
 | 
				
			||||||
 | 
					-- 
 | 
				
			||||||
 | 
					2.4.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,28 +44,15 @@
 | 
				
			||||||
  ;; This is QEMU without GUI support.
 | 
					  ;; This is QEMU without GUI support.
 | 
				
			||||||
  (package
 | 
					  (package
 | 
				
			||||||
    (name "qemu-headless")
 | 
					    (name "qemu-headless")
 | 
				
			||||||
    (version "2.3.1")
 | 
					    (version "2.4.0.1")
 | 
				
			||||||
    (source (origin
 | 
					    (source (origin
 | 
				
			||||||
             (method url-fetch)
 | 
					             (method url-fetch)
 | 
				
			||||||
             (uri (string-append "http://wiki.qemu-project.org/download/qemu-"
 | 
					             (uri (string-append "http://wiki.qemu-project.org/download/qemu-"
 | 
				
			||||||
                                 version ".tar.bz2"))
 | 
					                                 version ".tar.bz2"))
 | 
				
			||||||
             (sha256
 | 
					             (sha256
 | 
				
			||||||
              (base32
 | 
					              (base32
 | 
				
			||||||
               "0px1vhkglxzjdxkkqln98znv832n1sn79g5inh3aw72216c047b6"))
 | 
					               "1nqv5p94zpnhcaqkifnn83ap7dd0qrb0qiicswbyhhby0f48pzpc"))
 | 
				
			||||||
             (patches (map search-patch '("qemu-CVE-2015-3209.patch"
 | 
					             (patches (map search-patch '("qemu-CVE-2015-6855.patch")))))
 | 
				
			||||||
                                          "qemu-CVE-2015-4037.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4103.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4104.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4105.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt1.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt2.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt3.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt4.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt5.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt6.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt7.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-4106-pt8.patch"
 | 
					 | 
				
			||||||
                                          "qemu-CVE-2015-5745.patch")))))
 | 
					 | 
				
			||||||
    (build-system gnu-build-system)
 | 
					    (build-system gnu-build-system)
 | 
				
			||||||
    (arguments
 | 
					    (arguments
 | 
				
			||||||
     '(#:phases (alist-replace
 | 
					     '(#:phases (alist-replace
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue