[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 01/11] xen: properly gate host writes of modified PC
From: |
Stefano Stabellini |
Subject: |
[Qemu-devel] [PATCH 01/11] xen: properly gate host writes of modified PCI CFG contents |
Date: |
Tue, 2 Jun 2015 16:10:35 +0100 |
From: Jan Beulich <address@hidden>
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 <address@hidden>
Reviewed-by: Stefano Stabellini <address@hidden>
---
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,
--
1.7.10.4
- [Qemu-devel] [PATCH 0/11] Xen PCI Passthrough security fixes, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 01/11] xen: properly gate host writes of modified PCI CFG contents,
Stefano Stabellini <=
- [Qemu-devel] [PATCH 02/11] xen: don't allow guest to control MSI mask register, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 10/11] xen/pt: add a few PCI config space field descriptions, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 04/11] xen/MSI: don't open-code pass-through of enable bit modifications, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 07/11] xen/pt: split out calculation of throughable mask in PCI config space handling, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 08/11] xen/pt: mark all PCIe capability bits read-only, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 05/11] xen/pt: consolidate PM capability emu_mask, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 09/11] xen/pt: mark reserved bits in PCI config space fields, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 06/11] xen/pt: correctly handle PM status bit, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 03/11] xen/MSI-X: limit error messages, Stefano Stabellini, 2015/06/02
- [Qemu-devel] [PATCH 11/11] xen/pt: unknown PCI config space fields should be read-only, Stefano Stabellini, 2015/06/02