Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:Update
xen.787
CVE-2015-2756-xsa126.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2015-2756-xsa126.patch of Package xen.787
References: bsc#922706 CVE-2015-2756 XSA-126 xen: limit guest control of PCI command register Otherwise the guest can abuse that control to cause e.g. PCIe Unsupported Request responses (by disabling memory and/or I/O decoding and subsequently causing [CPU side] accesses to the respective address ranges), which (depending on system configuration) may be fatal to the host. This is CVE-2015-2756 / XSA-126. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- a/tools/qemu-xen-traditional-dir-remote/hw/pass-through.c +++ b/tools/qemu-xen-traditional-dir-remote/hw/pass-through.c @@ -172,9 +172,6 @@ static int pt_word_reg_read(struct pt_de static int pt_long_reg_read(struct pt_dev *ptdev, struct pt_reg_tbl *cfg_entry, uint32_t *value, uint32_t valid_mask); -static int pt_cmd_reg_read(struct pt_dev *ptdev, - struct pt_reg_tbl *cfg_entry, - uint16_t *value, uint16_t valid_mask); static int pt_bar_reg_read(struct pt_dev *ptdev, struct pt_reg_tbl *cfg_entry, uint32_t *value, uint32_t valid_mask); @@ -286,9 +283,9 @@ static struct pt_reg_info_tbl pt_emu_reg .size = 2, .init_val = 0x0000, .ro_mask = 0xF880, - .emu_mask = 0x0740, + .emu_mask = 0x0743, .init = pt_common_reg_init, - .u.w.read = pt_cmd_reg_read, + .u.w.read = pt_word_reg_read, .u.w.write = pt_cmd_reg_write, .u.w.restore = pt_cmd_reg_restore, }, @@ -1905,7 +1902,7 @@ static int pt_dev_is_virtfn(struct pci_d return rc; } -static int pt_register_regions(struct pt_dev *assigned_device) +static int pt_register_regions(struct pt_dev *assigned_device, uint16_t *cmd) { int i = 0; uint32_t bar_data = 0; @@ -1925,17 +1922,26 @@ static int pt_register_regions(struct pt /* Register current region */ if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_IO ) + { pci_register_io_region((PCIDevice *)assigned_device, i, (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO, pt_ioport_map); + *cmd |= PCI_COMMAND_IO; + } else if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_MEM_PREFETCH ) + { pci_register_io_region((PCIDevice *)assigned_device, i, (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH, pt_iomem_map); + *cmd |= PCI_COMMAND_MEMORY; + } else + { pci_register_io_region((PCIDevice *)assigned_device, i, (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM, pt_iomem_map); + *cmd |= PCI_COMMAND_MEMORY; + } PT_LOG("IO region registered (size=0x%08x base_addr=0x%08x)\n", (uint32_t)(pci_dev->size[i]), @@ -3263,27 +3269,6 @@ static int pt_long_reg_read(struct pt_de return 0; } -/* read Command register */ -static int pt_cmd_reg_read(struct pt_dev *ptdev, - struct pt_reg_tbl *cfg_entry, - uint16_t *value, uint16_t valid_mask) -{ - struct pt_reg_info_tbl *reg = cfg_entry->reg; - uint16_t valid_emu_mask = 0; - uint16_t emu_mask = reg->emu_mask; - - if ( ptdev->is_virtfn ) - emu_mask |= PCI_COMMAND_MEMORY; - if ( pt_is_iomul(ptdev) ) - emu_mask |= PCI_COMMAND_IO; - - /* emulate word register */ - valid_emu_mask = emu_mask & valid_mask; - *value = PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); - - return 0; -} - /* read BAR */ static int pt_bar_reg_read(struct pt_dev *ptdev, struct pt_reg_tbl *cfg_entry, @@ -3418,19 +3403,13 @@ static int pt_cmd_reg_write(struct pt_de uint16_t writable_mask = 0; uint16_t throughable_mask = 0; uint16_t wr_value = *value; - uint16_t emu_mask = reg->emu_mask; - - if ( ptdev->is_virtfn ) - emu_mask |= PCI_COMMAND_MEMORY; - if ( pt_is_iomul(ptdev) ) - emu_mask |= PCI_COMMAND_IO; /* modify emulate register */ writable_mask = ~reg->ro_mask & valid_mask; cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); /* create value for writing to I/O device register */ - throughable_mask = ~emu_mask & valid_mask; + throughable_mask = ~reg->emu_mask & valid_mask; if (*value & PCI_COMMAND_DISABLE_INTx) { @@ -4211,6 +4190,7 @@ static struct pt_dev * register_real_dev struct pt_dev *assigned_device = NULL; struct pci_dev *pci_dev; uint8_t e_device, e_intx; + uint16_t cmd = 0; char *key, *val; int msi_translate, power_mgmt; @@ -4300,7 +4280,7 @@ static struct pt_dev * register_real_dev assigned_device->dev.config[i] = pci_read_byte(pci_dev, i); /* Handle real device's MMIO/PIO BARs */ - pt_register_regions(assigned_device); + pt_register_regions(assigned_device, &cmd); /* Setup VGA bios for passthroughed gfx */ if ( setup_vga_pt(assigned_device) < 0 ) @@ -4378,6 +4358,10 @@ static struct pt_dev * register_real_dev } out: + if (cmd) + pci_write_word(pci_dev, PCI_COMMAND, + *(uint16_t *)(&assigned_device->dev.config[PCI_COMMAND]) | cmd); + PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n" "IRQ type = %s\n", r_bus, r_dev, r_func, assigned_device->msi_trans_en? "MSI-INTx":"INTx"); --- a/tools/qemu-xen-dir-remote/hw/xen/xen_pt.c +++ b/tools/qemu-xen-dir-remote/hw/xen/xen_pt.c @@ -388,7 +388,7 @@ static const MemoryRegionOps ops = { .write = xen_pt_bar_write, }; -static int xen_pt_register_regions(XenPCIPassthroughState *s) +static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd) { int i = 0; XenHostPCIDevice *d = &s->real_device; @@ -406,6 +406,7 @@ static int xen_pt_register_regions(XenPC if (r->type & XEN_HOST_PCI_REGION_TYPE_IO) { type = PCI_BASE_ADDRESS_SPACE_IO; + *cmd |= PCI_COMMAND_IO; } else { type = PCI_BASE_ADDRESS_SPACE_MEMORY; if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) { @@ -414,6 +415,7 @@ static int xen_pt_register_regions(XenPC if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) { type |= PCI_BASE_ADDRESS_MEM_TYPE_64; } + *cmd |= PCI_COMMAND_MEMORY; } memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev, @@ -656,6 +658,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 */ @@ -690,7 +693,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)) { @@ -754,6 +757,11 @@ static int xen_pt_initfn(PCIDevice *d) } out: + if (cmd) { + xen_host_pci_set_word(&s->real_device, PCI_COMMAND, + pci_get_word(d->config + PCI_COMMAND) | cmd); + } + memory_listener_register(&s->memory_listener, &address_space_memory); memory_listener_register(&s->io_listener, &address_space_io); XEN_PT_LOG(d, --- a/tools/qemu-xen-dir-remote/hw/xen/xen_pt_config_init.c +++ b/tools/qemu-xen-dir-remote/hw/xen/xen_pt_config_init.c @@ -286,23 +286,6 @@ static int xen_pt_irqpin_reg_init(XenPCI } /* Command register */ -static int xen_pt_cmd_reg_read(XenPCIPassthroughState *s, XenPTReg *cfg_entry, - uint16_t *value, uint16_t valid_mask) -{ - XenPTRegInfo *reg = cfg_entry->reg; - uint16_t valid_emu_mask = 0; - uint16_t emu_mask = reg->emu_mask; - - if (s->is_virtfn) { - emu_mask |= PCI_COMMAND_MEMORY; - } - - /* emulate word register */ - valid_emu_mask = emu_mask & valid_mask; - *value = XEN_PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask); - - return 0; -} static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, uint16_t *val, uint16_t dev_value, uint16_t valid_mask) @@ -310,18 +293,13 @@ static int xen_pt_cmd_reg_write(XenPCIPa XenPTRegInfo *reg = cfg_entry->reg; uint16_t writable_mask = 0; uint16_t throughable_mask = 0; - uint16_t emu_mask = reg->emu_mask; - - if (s->is_virtfn) { - emu_mask |= PCI_COMMAND_MEMORY; - } /* modify emulate register */ writable_mask = ~reg->ro_mask & valid_mask; cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); /* create value for writing to I/O device register */ - throughable_mask = ~emu_mask & valid_mask; + throughable_mask = ~reg->emu_mask & valid_mask; if (*val & PCI_COMMAND_INTX_DISABLE) { throughable_mask |= PCI_COMMAND_INTX_DISABLE; @@ -605,9 +583,9 @@ static XenPTRegInfo xen_pt_emu_reg_heade .size = 2, .init_val = 0x0000, .ro_mask = 0xF880, - .emu_mask = 0x0740, + .emu_mask = 0x0743, .init = xen_pt_common_reg_init, - .u.w.read = xen_pt_cmd_reg_read, + .u.w.read = xen_pt_word_reg_read, .u.w.write = xen_pt_cmd_reg_write, }, /* Capabilities Pointer reg */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor