diff options
Diffstat (limited to 'gnu/packages/patches/qemu-CVE-2015-4103.patch')
-rw-r--r-- | gnu/packages/patches/qemu-CVE-2015-4103.patch | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/gnu/packages/patches/qemu-CVE-2015-4103.patch b/gnu/packages/patches/qemu-CVE-2015-4103.patch new file mode 100644 index 0000000000..74333fd672 --- /dev/null +++ b/gnu/packages/patches/qemu-CVE-2015-4103.patch @@ -0,0 +1,135 @@ +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 + |