summaryrefslogtreecommitdiffstats
path: root/hw/xen/xen_pt.c
diff options
context:
space:
mode:
authorJan Beulich2015-03-31 16:18:03 +0200
committerPeter Maydell2015-04-10 00:37:21 +0200
commit81b23ef82cd1be29ca3d69ab7e98b5b5e55926ce (patch)
tree32abd64c12c5e0b8da5e524da43bad71095bbda2 /hw/xen/xen_pt.c
parentconfigure: disable Archipelago by default and warn about libxseg GPLv3 license (diff)
downloadqemu-81b23ef82cd1be29ca3d69ab7e98b5b5e55926ce.tar.gz
qemu-81b23ef82cd1be29ca3d69ab7e98b5b5e55926ce.tar.xz
qemu-81b23ef82cd1be29ca3d69ab7e98b5b5e55926ce.zip
xen: limit guest control of PCI command register
Otherwise the guest can abuse that control to cause e.g. PCIe Unsupported Request responses (by disabling memory and/or I/O decoding and subsequently causing [CPU side] accesses to the respective address ranges), which (depending on system configuration) may be fatal to the host. This is CVE-2015-2756 / XSA-126. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Message-id: alpine.DEB.2.02.1503311510300.7690@kaball.uk.xensource.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/xen/xen_pt.c')
-rw-r--r--hw/xen/xen_pt.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index f2893b28aa..d095c081cc 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -388,7 +388,7 @@ static const MemoryRegionOps ops = {
.write = xen_pt_bar_write,
};
-static int xen_pt_register_regions(XenPCIPassthroughState *s)
+static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd)
{
int i = 0;
XenHostPCIDevice *d = &s->real_device;
@@ -406,6 +406,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
if (r->type & XEN_HOST_PCI_REGION_TYPE_IO) {
type = PCI_BASE_ADDRESS_SPACE_IO;
+ *cmd |= PCI_COMMAND_IO;
} else {
type = PCI_BASE_ADDRESS_SPACE_MEMORY;
if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) {
@@ -414,6 +415,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) {
type |= PCI_BASE_ADDRESS_MEM_TYPE_64;
}
+ *cmd |= PCI_COMMAND_MEMORY;
}
memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev,
@@ -638,6 +640,7 @@ static int xen_pt_initfn(PCIDevice *d)
XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
int rc = 0;
uint8_t machine_irq = 0;
+ uint16_t cmd = 0;
int pirq = XEN_PT_UNASSIGNED_PIRQ;
/* register real device */
@@ -672,7 +675,7 @@ static int xen_pt_initfn(PCIDevice *d)
s->io_listener = xen_pt_io_listener;
/* Handle real device's MMIO/PIO BARs */
- xen_pt_register_regions(s);
+ xen_pt_register_regions(s, &cmd);
/* reinitialize each config register to be emulated */
if (xen_pt_config_init(s)) {
@@ -736,6 +739,11 @@ static int xen_pt_initfn(PCIDevice *d)
}
out:
+ if (cmd) {
+ xen_host_pci_set_word(&s->real_device, PCI_COMMAND,
+ pci_get_word(d->config + PCI_COMMAND) | cmd);
+ }
+
memory_listener_register(&s->memory_listener, &s->dev.bus_master_as);
memory_listener_register(&s->io_listener, &address_space_io);
XEN_PT_LOG(d,