From 97f3bec381b1f2d61079b1e5dc44a01e8213a136 Mon Sep 17 00:00:00 2001 From: Michael Young Date: Mar 09 2016 22:04:13 +0000 Subject: many qemu security issues --- diff --git a/qemu.CVE-2015-8613.patch b/qemu.CVE-2015-8613.patch new file mode 100644 index 0000000..72adfdd --- /dev/null +++ b/qemu.CVE-2015-8613.patch @@ -0,0 +1,29 @@ +From: Prasad J Pandit +Date: Mon, 21 Dec 2015 14:48:18 +0530 +Subject: [PATCH] scsi: initialise info object with appropriate size + +While processing controller 'CTRL_GET_INFO' command, the routine +'megasas_ctrl_get_info' overflows the '&info' object size. Use its +appropriate size to null initialise it. + +Reported-by: Qinghao Tang +Signed-off-by: Prasad J Pandit +--- + hw/scsi/megasas.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c +index d7dc667..576f56c 100644 +--- a/tools/qemu-xen/hw/scsi/megasas.c ++++ b/tools/qemu-xen/hw/scsi/megasas.c +@@ -718,7 +718,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) + int num_ld_disks = 0; + uint16_t sdev_id; + +- memset(&info, 0x0, cmd->iov_size); ++ memset(&info, 0x0, dcmd_size); + if (cmd->iov_size < dcmd_size) { + trace_megasas_dcmd_invalid_xfer_len(cmd->index, cmd->iov_size, + dcmd_size); +-- +2.4.3 diff --git a/qemu.CVE-2015-8817+8.patch b/qemu.CVE-2015-8817+8.patch new file mode 100644 index 0000000..efb77c6 --- /dev/null +++ b/qemu.CVE-2015-8817+8.patch @@ -0,0 +1,224 @@ +From 965eb2fcdfe919ecced6c34803535ad32dc1249c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 17 Jun 2015 10:40:27 +0200 +Subject: [PATCH] exec: do not clamp accesses to MMIO regions +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +It is common for MMIO registers to overlap, for example a 4 byte register +at 0xcf8 (totally random choice... :)) and a 1 byte register at 0xcf9. +If these registers are implemented via separate MemoryRegions, it is +wrong to clamp the accesses as the value written would be truncated. + +Hence for these regions the effects of commit 23820db (exec: Respect +as_translate_internal length clamp, 2015-03-16, previously applied as +commit c3c1bb99) must be skipped. + +Tested-by: Hervé Poussineau +Tested-by: Mark Cave-Ayland +Signed-off-by: Paolo Bonzini +--- + exec.c | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/exec.c b/exec.c +index 76bfc4a..d00e017 100644 +--- a/tools/qemu-xen/exec.c ++++ b/tools/qemu-xen/exec.c +@@ -341,6 +341,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x + hwaddr *plen, bool resolve_subpage) + { + MemoryRegionSection *section; ++ MemoryRegion *mr; + Int128 diff; + + section = address_space_lookup_region(d, addr, resolve_subpage); +@@ -350,8 +351,11 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x + /* Compute offset within MemoryRegion */ + *xlat = addr + section->offset_within_region; + +- diff = int128_sub(section->mr->size, int128_make64(addr)); +- *plen = int128_get64(int128_min(diff, int128_make64(*plen))); ++ mr = section->mr; ++ if (memory_region_is_ram(mr)) { ++ diff = int128_sub(mr->size, int128_make64(addr)); ++ *plen = int128_get64(int128_min(diff, int128_make64(*plen))); ++ } + return section; + } + +-- +1.7.0.4 + +From e4a511f8cc6f4a46d409fb5c9f72c38ba45f8d83 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 17 Jun 2015 10:36:54 +0200 +Subject: [PATCH] exec: clamp accesses against the MemoryRegionSection +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Because the clamping was done against the MemoryRegion, +address_space_rw was effectively broken if a write spanned +multiple sections that are not linear in underlying memory +(with the memory not being under an IOMMU). + +This is visible with the MIPS rc4030 IOMMU, which is implemented +as a series of alias memory regions that point to the actual RAM. + +Tested-by: Hervé Poussineau +Tested-by: Mark Cave-Ayland +Signed-off-by: Paolo Bonzini +--- + exec.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/exec.c b/exec.c +index d00e017..f7883d2 100644 +--- a/tools/qemu-xen/exec.c ++++ b/tools/qemu-xen/exec.c +@@ -353,7 +353,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x + + mr = section->mr; + if (memory_region_is_ram(mr)) { +- diff = int128_sub(mr->size, int128_make64(addr)); ++ diff = int128_sub(section->size, int128_make64(addr)); + *plen = int128_get64(int128_min(diff, int128_make64(*plen))); + } + return section; +-- +1.7.0.4 + +From b242e0e0e2969c044a318e56f7988bbd84de1f63 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Sat, 4 Jul 2015 00:24:51 +0200 +Subject: [PATCH] exec: skip MMIO regions correctly in cpu_physical_memory_write_rom_internal + +Loading the BIOS in the mac99 machine is interesting, because there is a +PROM in the middle of the BIOS region (from 16K to 32K). Before memory +region accesses were clamped, when QEMU was asked to load a BIOS from +0xfff00000 to 0xffffffff it would put even those 16K from the BIOS file +into the region. This is weird because those 16K were not actually +visible between 0xfff04000 and 0xfff07fff. However, it worked. + +After clamping was added, this also worked. In this case, the +cpu_physical_memory_write_rom_internal function split the write in +three parts: the first 16K were copied, the PROM area (second 16K) were +ignored, then the rest was copied. + +Problems then started with commit 965eb2f (exec: do not clamp accesses +to MMIO regions, 2015-06-17). Clamping accesses is not done for MMIO +regions because they can overlap wildly, and MMIO registers can be +expected to perform full-width accesses based only on their address +(with no respect for adjacent registers that could decode to completely +different MemoryRegions). However, this lack of clamping also applied +to the PROM area! cpu_physical_memory_write_rom_internal thus failed +to copy the third range above, i.e. only copied the first 16K of the BIOS. + +In effect, address_space_translate is expecting _something else_ to do +the clamping for MMIO regions if the incoming length is large. This +"something else" is memory_access_size in the case of address_space_rw, +so use the same logic in cpu_physical_memory_write_rom_internal. + +Reported-by: Alexander Graf +Reviewed-by: Laurent Vivier +Tested-by: Laurent Vivier +Fixes: 965eb2f +Signed-off-by: Paolo Bonzini +--- + exec.c | 14 +++++++++++++- + 1 files changed, 13 insertions(+), 1 deletions(-) + +diff --git a/exec.c b/exec.c +index 3457f7e..251dc79 100644 +--- a/tools/qemu-xen/exec.c ++++ b/tools/qemu-xen/exec.c +@@ -353,6 +353,18 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x + *xlat = addr + section->offset_within_region; + + mr = section->mr; ++ ++ /* MMIO registers can be expected to perform full-width accesses based only ++ * on their address, without considering adjacent registers that could ++ * decode to completely different MemoryRegions. When such registers ++ * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO ++ * regions overlap wildly. For this reason we cannot clamp the accesses ++ * here. ++ * ++ * If the length is small (as is the case for address_space_ldl/stl), ++ * everything works fine. If the incoming length is large, however, ++ * the caller really has to do the clamping through memory_access_size. ++ */ + if (memory_region_is_ram(mr)) { + diff = int128_sub(section->size, int128_make64(addr)); + *plen = int128_get64(int128_min(diff, int128_make64(*plen))); +@@ -2491,7 +2503,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, + + if (!(memory_region_is_ram(mr) || + memory_region_is_romd(mr))) { +- /* do nothing */ ++ l = memory_access_size(mr, l, addr1); + } else { + addr1 += memory_region_get_ram_addr(mr); + /* ROM/RAM case */ +-- +1.7.0.4 + +From c3c1bb99d1c11978d9ce94d1bdcf0705378c1459 Mon Sep 17 00:00:00 2001 +From: Peter Crosthwaite +Date: Mon, 16 Mar 2015 22:35:54 -0700 +Subject: [PATCH] exec: Respect as_tranlsate_internal length clamp + +address_space_translate_internal will clamp the *plen length argument +based on the size of the memory region being queried. The iommu walker +logic in addresss_space_translate was ignoring this by discarding the +post fn call value of *plen. Fix by just always using *plen as the +length argument throughout the fn, removing the len local variable. + +This fixes a bootloader bug when a single elf section spans multiple +QEMU memory regions. + +Signed-off-by: Peter Crosthwaite +Message-Id: <1426570554-15940-1-git-send-email-peter.crosthwaite@xilinx.com> +Signed-off-by: Paolo Bonzini +--- + exec.c | 6 ++---- + 1 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/exec.c b/exec.c +index e97071a..8b922db 100644 +--- a/tools/qemu-xen/exec.c ++++ b/tools/qemu-xen/exec.c +@@ -380,7 +380,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, + IOMMUTLBEntry iotlb; + MemoryRegionSection *section; + MemoryRegion *mr; +- hwaddr len = *plen; + + for (;;) { + section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true); +@@ -395,7 +394,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, + iotlb = mr->iommu_ops->translate(mr, addr); + addr = ((iotlb.translated_addr & ~iotlb.addr_mask) + | (addr & iotlb.addr_mask)); +- len = MIN(len, (addr | iotlb.addr_mask) - addr + 1); ++ *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); + if (!(iotlb.perm & (1 << is_write))) { + mr = &io_mem_unassigned; + break; +@@ -406,10 +405,9 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, + + if (xen_enabled() && memory_access_is_direct(mr, is_write)) { + hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; +- len = MIN(page, len); ++ *plen = MIN(page, *plen); + } + +- *plen = len; + *xlat = addr; + return mr; + } +-- +1.7.0.4 + diff --git a/qemu.CVE-2016-1714.patch b/qemu.CVE-2016-1714.patch new file mode 100644 index 0000000..a42528c --- /dev/null +++ b/qemu.CVE-2016-1714.patch @@ -0,0 +1,50 @@ +From: Prasad J Pandit + +When processing firmware configurations, an OOB r/w access occurs +if 's->cur_entry' is set to be invalid(FW_CFG_INVALID=0xffff). +Add a check to validate 's->cur_entry' to avoid such access. + +Reported-by: Donghai Zdh +Signed-off-by: Prasad J Pandit +--- + hw/nvram/fw_cfg.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +Updated as per review in + -> https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg00398.html + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 68eff77..e73c0fb 100644 +--- a/tools/qemu-xen/hw/nvram/fw_cfg.c ++++ b/tools/qemu-xen/hw/nvram/fw_cfg.c +@@ -233,12 +233,15 @@ static void fw_cfg_reboot(FWCfgState *s) + static void fw_cfg_write(FWCfgState *s, uint8_t value) + { + int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL); +- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; ++ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL : ++ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; + + trace_fw_cfg_write(s, value); + +- if (s->cur_entry & FW_CFG_WRITE_CHANNEL && e->callback && +- s->cur_offset < e->len) { ++ if (s->cur_entry & FW_CFG_WRITE_CHANNEL ++ && e != NULL ++ && e->callback ++ && s->cur_offset < e->len) { + e->data[s->cur_offset++] = value; + if (s->cur_offset == e->len) { + e->callback(e->callback_opaque, e->data); +@@ -267,7 +270,8 @@ static int fw_cfg_select(FWCfgState *s, uint16_t key) + static uint8_t fw_cfg_read(FWCfgState *s) + { + int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL); +- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; ++ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL : ++ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; + uint8_t ret; + + if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len) +-- +2.4.3 diff --git a/qemu.CVE-2016-1922.patch b/qemu.CVE-2016-1922.patch new file mode 100644 index 0000000..b4940f3 --- /dev/null +++ b/qemu.CVE-2016-1922.patch @@ -0,0 +1,45 @@ +From: Prasad J Pandit + +When I/O port write operation is called from hmp interface, +'current_cpu' remains null, as it is not called from cpu_exec() +loop. This leads to a null pointer dereference in vapic_write +routine. Add check to avoid it. + +Reported-by: Ling Liu +Signed-off-by: Prasad J Pandit +Message-Id: +Signed-off-by: Paolo Bonzini +--- + hw/i386/kvmvapic.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index c6d34b2..f0922da 100644 +--- a/tools/qemu-xen/hw/i386/kvmvapic.c ++++ b/tools/qemu-xen/hw/i386/kvmvapic.c +@@ -634,13 +634,18 @@ static int vapic_prepare(VAPICROMState *s) + static void vapic_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) + { +- CPUState *cs = current_cpu; +- X86CPU *cpu = X86_CPU(cs); +- CPUX86State *env = &cpu->env; +- hwaddr rom_paddr; + VAPICROMState *s = opaque; ++ X86CPU *cpu; ++ CPUX86State *env; ++ hwaddr rom_paddr; + +- cpu_synchronize_state(cs); ++ if (!current_cpu) { ++ return; ++ } ++ ++ cpu_synchronize_state(current_cpu); ++ cpu = X86_CPU(current_cpu); ++ env = &cpu->env; + + /* + * The VAPIC supports two PIO-based hypercalls, both via port 0x7E. +-- +1.8.3.1 diff --git a/qemu.CVE-2016-1981.patch b/qemu.CVE-2016-1981.patch new file mode 100644 index 0000000..474fc62 --- /dev/null +++ b/qemu.CVE-2016-1981.patch @@ -0,0 +1,104 @@ +------------------------------------------------------------------------ +*From*: Laszlo Ersek +*Subject*: [Qemu-devel] [PATCH] e1000: eliminate infinite loops on +out-of-bounds transfer start +*Date*: Tue, 19 Jan 2016 14:17:20 +0100 + +------------------------------------------------------------------------ + +The start_xmit() and e1000_receive_iov() functions implement DMA transfers +iterating over a set of descriptors that the guest's e1000 driver +prepares: + +- the TDLEN and RDLEN registers store the total size of the descriptor + area, + +- while the TDH and RDH registers store the offset (in whole tx / rx + descriptors) into the area where the transfer is supposed to start. + +Each time a descriptor is processed, the TDH and RDH register is bumped +(as appropriate for the transfer direction). + +QEMU already contains logic to deal with bogus transfers submitted by the +guest: + +- Normally, the transmit case wants to increase TDH from its initial value + to TDT. (TDT is allowed to be numerically smaller than the initial TDH + value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe + that QEMU currently has here is a check against reaching the original + TDH value again -- a complete wraparound, which should never happen. + +- In the receive case RDH is increased from its initial value until + "total_size" bytes have been received; preferably in a single step, or + in "s->rxbuf_size" byte steps, if the latter is smaller. However, null + RX descriptors are skipped without receiving data, while RDH is + incremented just the same. QEMU tries to prevent an infinite loop + (processing only null RX descriptors) by detecting whether RDH assumes + its original value during the loop. (Again, wrapping from RDLEN to 0 is + normal.) + +What both directions miss is that the guest could program TDLEN and RDLEN +so low, and the initial TDH and RDH so high, that these registers will +immediately be truncated to zero, and then never reassume their initial +values in the loop -- a full wraparound will never occur. + +The condition that expresses this is: + + xdh_start >= s->mac_reg[XDLEN] / sizeof(desc) + +i.e., TDH or RDH start out after the last whole rx or tx descriptor that +fits into the TDLEN or RDLEN sized area. + +This condition could be checked before we enter the loops, but +pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for +bogus DMA addresses, so we just extend the existing failsafes with the +above condition. + +Cc: "Michael S. Tsirkin" +Cc: Petr Matousek +Cc: Stefano Stabellini +Cc: Prasad Pandit +Cc: Michael Roth +Cc: Jason Wang +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044 +Signed-off-by: Laszlo Ersek +Reviewed-by: Jason Wang +--- + +Notes: + Regarding the public posting: we made an honest effort to vet this + vulnerability, and the impact seems low -- no host side reads/writes, + "just" a DoS (infinite loop). We decided the patch could be posted + publicly, for the usual review process. Jason and Prasad checked the + patch in the internal discussion already, but comments, improvements + etc. are clearly welcome. The CVE request is underway. Thanks. + + hw/net/e1000.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index bec06e9..34d0823 100644 +--- a/tools/qemu-xen/hw/net/e1000.c ++++ b/tools/qemu-xen/hw/net/e1000.c +@@ -908,7 +908,8 @@ start_xmit(E1000State *s) + * bogus values to TDT/TDLEN. + * there's nothing too intelligent we could do about this. + */ +- if (s->mac_reg[TDH] == tdh_start) { ++ if (s->mac_reg[TDH] == tdh_start || ++ tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) { + DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", + tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); + break; +@@ -1165,7 +1166,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) + if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) + s->mac_reg[RDH] = 0; + /* see comment in start_xmit; same here */ +- if (s->mac_reg[RDH] == rdh_start) { ++ if (s->mac_reg[RDH] == rdh_start || ++ rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) { + DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", + rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); + set_ics(s, 0, E1000_ICS_RXO); +-- +1.8.3.1 diff --git a/qemu.CVE-2016-2198.patch b/qemu.CVE-2016-2198.patch new file mode 100644 index 0000000..7fd10dc --- /dev/null +++ b/qemu.CVE-2016-2198.patch @@ -0,0 +1,40 @@ +From: Prasad J Pandit + +USB Ehci emulation supports host controller capability registers. +But its mmio '.write' function was missing, which lead to a null +pointer dereference issue. Add a do nothing 'ehci_caps_write' +definition to avoid it; Do nothing because capability registers +are Read Only(RO). + +Reported-by: Zuozhi Fzz +Signed-off-by: Prasad J Pandit +--- + hw/usb/hcd-ehci.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index c40013e..b08ff62 100644 +--- a/tools/qemu-xen/hw/usb/hcd-ehci.c ++++ b/tools/qemu-xen/hw/usb/hcd-ehci.c +@@ -893,6 +893,11 @@ static uint64_t ehci_caps_read(void *ptr, hwaddr addr, + return s->caps[addr]; + } + ++static void ehci_caps_write(void *ptr, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++} ++ + static uint64_t ehci_opreg_read(void *ptr, hwaddr addr, + unsigned size) + { +@@ -2313,6 +2318,7 @@ static void ehci_frame_timer(void *opaque) + + static const MemoryRegionOps ehci_mmio_caps_ops = { + .read = ehci_caps_read, ++ .write = ehci_caps_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, +-- +2.5.0 diff --git a/qemu.CVE-2016-2391.patch b/qemu.CVE-2016-2391.patch new file mode 100644 index 0000000..d9e0169 --- /dev/null +++ b/qemu.CVE-2016-2391.patch @@ -0,0 +1,55 @@ +From d1b07becc481e09225cfe905ec357807ae07f095 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Feb 2016 15:15:04 +0100 +Subject: [PATCH] ohci timer fix + +Signed-off-by: Gerd Hoffmann +--- + hw/usb/hcd-ohci.c | 31 +++++-------------------------- + 1 file changed, 5 insertions(+), 26 deletions(-) + +diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c +index bed55dd..3d1270d 100644 +--- a/tools/qemu-xen/hw/usb/hcd-ohci.c ++++ b/tools/qemu-xen/hw/usb/hcd-ohci.c +@@ -1347,16 +1347,6 @@ static void ohci_frame_boundary(void *opaque) + */ + static int ohci_bus_start(OHCIState *ohci) + { +- ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, +- ohci_frame_boundary, +- ohci); +- +- if (ohci->eof_timer == NULL) { +- fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name); +- ohci_die(ohci); +- return 0; +- } +- + DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name); + + ohci_sof(ohci); +@@ -1373,9 +1363,7 @@ static int ohci_bus_start(OHCIState *ohci) + /* Stop sending SOF tokens on the bus */ + static void ohci_bus_stop(OHCIState *ohci) + { +- if (ohci->eof_timer) +- timer_del(ohci->eof_timer); +- ohci->eof_timer = NULL; ++ timer_del(ohci->eof_timer); + } + + /* Sets a flag in a port status register but only set it if the port is +@@ -1907,6 +1893,9 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev, + ohci->async_td = 0; + qemu_register_reset(ohci_reset, ohci); + ++ ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ++ ohci_frame_boundary, ohci); ++ + return 0; + } + +-- +1.8.3.1 + diff --git a/qemu.CVE-2016-2392.patch b/qemu.CVE-2016-2392.patch new file mode 100644 index 0000000..ef71bea --- /dev/null +++ b/qemu.CVE-2016-2392.patch @@ -0,0 +1,29 @@ +From: Prasad J Pandit + +When processing remote NDIS control message packets, the USB Net +device emulator checks to see if the USB configuration descriptor +object is of RNDIS type(2). But it does not check if it is null, +which leads to a null dereference error. Add check to avoid it. + +Reported-by: Qinghao Tang +Signed-off-by: Prasad J Pandit +--- + hw/usb/dev-network.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index ba3c7a7..180adce 100644 +--- a/tools/qemu-xen/hw/usb/dev-network.c ++++ b/tools/qemu-xen/hw/usb/dev-network.c +@@ -653,7 +653,8 @@ typedef struct USBNetState { + + static int is_rndis(USBNetState *s) + { +- return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE; ++ return s->dev.config ? ++ s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE : 0; + } + + static int ndis_query(USBNetState *s, uint32_t oid, +-- +2.5.0 diff --git a/qemu.CVE-2016-2538.patch b/qemu.CVE-2016-2538.patch new file mode 100644 index 0000000..07e8089 --- /dev/null +++ b/qemu.CVE-2016-2538.patch @@ -0,0 +1,56 @@ +From: Prasad J Pandit + +When processing remote NDIS control message packets, +the USB Net device emulator uses a fixed length(4096) data buffer. +The incoming informationBufferOffset & Length combination could +overflow and cross that range. Check control message buffer +offsets and length to avoid it. + +Reported-by: Qinghao Tang +Signed-off-by: Prasad J Pandit +--- + hw/usb/dev-network.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +Update as per review + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg03475.html + +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 8a4ff49..180adce 100644 +--- a/tools/qemu-xen/hw/usb/dev-network.c ++++ b/tools/qemu-xen/hw/usb/dev-network.c +@@ -915,8 +915,9 @@ static int rndis_query_response(USBNetState *s, + + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8; + buflen = le32_to_cpu(buf->InformationBufferLength); +- if (bufoffs + buflen > length) ++ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) { + return USB_RET_STALL; ++ } + + infobuflen = ndis_query(s, le32_to_cpu(buf->OID), + bufoffs + (uint8_t *) buf, buflen, infobuf, +@@ -961,8 +962,9 @@ static int rndis_set_response(USBNetState *s, + + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8; + buflen = le32_to_cpu(buf->InformationBufferLength); +- if (bufoffs + buflen > length) ++ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) { + return USB_RET_STALL; ++ } + + ret = ndis_set(s, le32_to_cpu(buf->OID), + bufoffs + (uint8_t *) buf, buflen); +@@ -1212,8 +1214,9 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p) + if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) { + uint32_t offs = 8 + le32_to_cpu(msg->DataOffset); + uint32_t size = le32_to_cpu(msg->DataLength); +- if (offs + size <= len) ++ if (offs < len && size < len && offs + size <= len) { + qemu_send_packet(qemu_get_queue(s->nic), s->out_buf + offs, size); ++ } + } + s->out_ptr -= len; + memmove(s->out_buf, &s->out_buf[len], s->out_ptr); +-- +2.5.0 diff --git a/qemu.CVE-2016-2841.patch b/qemu.CVE-2016-2841.patch new file mode 100644 index 0000000..a49d10e --- /dev/null +++ b/qemu.CVE-2016-2841.patch @@ -0,0 +1,34 @@ +From: Prasad J Pandit + +Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152) +bytes to process network packets. Registers PSTART & PSTOP +define ring buffer size & location. Setting these registers +to invalid values could lead to infinite loop or OOB r/w +access issues. Add check to avoid it. + +Reported-by: Yang Hongke +Signed-off-by: Prasad J Pandit +--- + hw/net/ne2000.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Update per review: + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg05522.html + +diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c +index b032212..ced4666 100644 +--- a/tools/qemu-xen/hw/net/ne2000.c ++++ b/tools/qemu-xen/hw/net/ne2000.c +@@ -154,6 +154,10 @@ static int ne2000_buffer_full(NE2000State *s) + { + int avail, index, boundary; + ++ if (s->stop <= s->start) { ++ return 1; ++ } ++ + index = s->curpag << 8; + boundary = s->boundary << 8; + if (index < boundary) +-- +2.5.0 diff --git a/qemu.CVE-2016-2857.patch b/qemu.CVE-2016-2857.patch new file mode 100644 index 0000000..d6c108c --- /dev/null +++ b/qemu.CVE-2016-2857.patch @@ -0,0 +1,45 @@ +From: Prasad J Pandit + +While computing IP checksum, 'net_checksum_calculate' reads +payload length from the packet. It could exceed the given 'data' +buffer size. Add a check to avoid it. + +Reported-by: Liu Ling +Signed-off-by: Prasad J Pandit +--- + net/checksum.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +Update as per review: + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg06121.html + +diff --git a/net/checksum.c b/net/checksum.c +index 14c0855..0942437 100644 +--- a/tools/qemu-xen/net/checksum.c ++++ b/tools/qemu-xen/net/checksum.c +@@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length) + int hlen, plen, proto, csum_offset; + uint16_t csum; + ++ /* Ensure data has complete L2 & L3 headers. */ ++ if (length < 14 + 20) { ++ return; ++ } ++ + if ((data[14] & 0xf0) != 0x40) + return; /* not IPv4 */ + hlen = (data[14] & 0x0f) * 4; +@@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length) + return; + } + +- if (plen < csum_offset+2) +- return; ++ if (plen < csum_offset + 2 || 14 + hlen + plen > length) { ++ return; ++ } + + data[14+hlen+csum_offset] = 0; + data[14+hlen+csum_offset+1] = 0; +-- +2.5.0 diff --git a/qemu.bug1300235.patch b/qemu.bug1300235.patch new file mode 100644 index 0000000..22cd8ab --- /dev/null +++ b/qemu.bug1300235.patch @@ -0,0 +1,46 @@ +From: Prasad J Pandit + +While processing isochronous transfer descriptors(iTD), the page +select(PG) field value could lead to an OOB read access. Add +check to avoid it. + +Reported-by: Qinghao Tang +Signed-off-by: Prasad J Pandit +--- + hw/usb/hcd-ehci.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index d07f228..c40013e 100644 +--- a/tools/qemu-xen/hw/usb/hcd-ehci.c ++++ b/tools/qemu-xen/hw/usb/hcd-ehci.c +@@ -1404,21 +1404,23 @@ static int ehci_process_itd(EHCIState *ehci, + if (itd->transact[i] & ITD_XACT_ACTIVE) { + pg = get_field(itd->transact[i], ITD_XACT_PGSEL); + off = itd->transact[i] & ITD_XACT_OFFSET_MASK; +- ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK); +- ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK); + len = get_field(itd->transact[i], ITD_XACT_LENGTH); + + if (len > max * mult) { + len = max * mult; + } +- +- if (len > BUFF_SIZE) { ++ if (len > BUFF_SIZE || pg > 6) { + return -1; + } + ++ ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK); + qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as); + if (off + len > 4096) { + /* transfer crosses page border */ ++ if (pg == 6) { ++ return -1; /* avoid page pg + 1 */ ++ } ++ ptr2 = (itd->bufptr[pg + 1] & ITD_BUFPTR_MASK); + uint32_t len2 = off + len - 4096; + uint32_t len1 = len - len2; + qemu_sglist_add(&ehci->isgl, ptr1 + off, len1); +-- +2.5.0 diff --git a/qemu.git-60253ed1e6ec6d8e5ef2efe7bf755f475.patch b/qemu.git-60253ed1e6ec6d8e5ef2efe7bf755f475.patch new file mode 100644 index 0000000..1bee196 --- /dev/null +++ b/qemu.git-60253ed1e6ec6d8e5ef2efe7bf755f475.patch @@ -0,0 +1,179 @@ +From 60253ed1e6ec6d8e5ef2efe7bf755f475dce9956 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Thu, 3 Mar 2016 09:37:18 +0100 +Subject: [PATCH] rng: add request queue support to rng-random + +Requests are now created in the RngBackend parent class and the +code path is shared by both rng-egd and rng-random. + +This commit fixes the rng-random implementation which processed +only one request at a time and simply discarded all but the most +recent one. In the guest this manifested as delayed completion +of reads from virtio-rng, i.e. a read was completed only after +another read was issued. + +By switching rng-random to use the same request queue as rng-egd, +the unsafe stack-based allocation of the entropy buffer is +eliminated and replaced with g_malloc. + +Signed-off-by: Ladi Prosek +Reviewed-by: Amit Shah +Message-Id: <1456994238-9585-5-git-send-email-lprosek@redhat.com> +Signed-off-by: Amit Shah +--- + backends/rng-egd.c | 16 ++-------------- + backends/rng-random.c | 43 +++++++++++++++++++------------------------ + backends/rng.c | 13 ++++++++++++- + include/sysemu/rng.h | 3 +-- + 4 files changed, 34 insertions(+), 41 deletions(-) + +diff --git a/backends/rng-egd.c b/backends/rng-egd.c +index 8f2bd16..30332ed 100644 +--- a/tools/qemu-xen/backends/rng-egd.c ++++ b/tools/qemu-xen/backends/rng-egd.c +@@ -27,20 +27,10 @@ typedef struct RngEgd + size_t size; + } RngRequest; + +-static void rng_egd_request_entropy(RngBackend *b, size_t size, +- EntropyReceiveFunc *receive_entropy, +- void *opaque) ++static void rng_egd_request_entropy(RngBackend *b, RngRequest *req) + { + RngEgd *s = RNG_EGD(b); +- RngRequest *req; +- +- req = g_malloc(sizeof(*req)); +- +- req->offset = 0; +- req->size = size; +- req->receive_entropy = receive_entropy; +- req->opaque = opaque; +- req->data = g_malloc(req->size); ++ size_t size = req->size; + + while (size > 0) { + uint8_t header[2]; +@@ -54,8 +44,6 @@ static void rng_egd_request_entropy(RngBackend *b, size_t size, + + size -= len; + } +- +- s->requests = g_slist_append(s->requests, req); + } + + static void rng_egd_free_request(RngRequest *req) +diff --git a/backends/rng-random.c b/backends/rng-random.c +index 8cdad6a..a6cb385 100644 +--- a/tools/qemu-xen/backends/rng-random.c ++++ b/tools/qemu-xen/backends/rng-random.c +@@ -22,10 +22,6 @@ struct RndRandom + + int fd; + char *filename; +- +- EntropyReceiveFunc *receive_func; +- void *opaque; +- size_t size; + }; + + /** +@@ -38,36 +34,35 @@ struct RndRandom + static void entropy_available(void *opaque) + { + RndRandom *s = RNG_RANDOM(opaque); +- uint8_t buffer[s->size]; +- ssize_t len; + +- len = read(s->fd, buffer, s->size); +- if (len < 0 && errno == EAGAIN) { +- return; +- } +- g_assert(len != -1); ++ while (s->parent.requests != NULL) { ++ RngRequest *req = s->parent.requests->data; ++ ssize_t len; ++ ++ len = read(s->fd, req->data, req->size); ++ if (len < 0 && errno == EAGAIN) { ++ return; ++ } ++ g_assert(len != -1); + +- s->receive_func(s->opaque, buffer, len); +- s->receive_func = NULL; ++ req->receive_entropy(req->opaque, req->data, len); + ++ rng_backend_finalize_request(&s->parent, req); ++ } ++ ++ /* We've drained all requests, the fd handler can be reset. */ + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + } + +-static void rng_random_request_entropy(RngBackend *b, size_t size, +- EntropyReceiveFunc *receive_entropy, +- void *opaque) ++static void rng_random_request_entropy(RngBackend *b, RngRequest *req) + { + RndRandom *s = RNG_RANDOM(b); + +- if (s->receive_func) { +- s->receive_func(s->opaque, NULL, 0); ++ if (s->parent.requests == NULL) { ++ /* If there are no pending requests yet, we need to ++ * install our fd handler. */ ++ qemu_set_fd_handler(s->fd, entropy_available, NULL, s); + } +- +- s->receive_func = receive_entropy; +- s->opaque = opaque; +- s->size = size; +- +- qemu_set_fd_handler(s->fd, entropy_available, NULL, s); + } + + static void rng_random_opened(RngBackend *b, Error **errp) +diff --git a/backends/rng.c b/backends/rng.c +index 014cb9d..277a41b 100644 +--- a/tools/qemu-xen/backends/rng.c ++++ b/tools/qemu-xen/backends/rng.c +@@ -20,9 +20,20 @@ void rng_backend_request_entropy(RngBackend *s, size_t size, + void *opaque) + { + RngBackendClass *k = RNG_BACKEND_GET_CLASS(s); ++ RngRequest *req; + + if (k->request_entropy) { +- k->request_entropy(s, size, receive_entropy, opaque); ++ req = g_malloc(sizeof(*req)); ++ ++ req->offset = 0; ++ req->size = size; ++ req->receive_entropy = receive_entropy; ++ req->opaque = opaque; ++ req->data = g_malloc(req->size); ++ ++ k->request_entropy(s, req); ++ ++ s->requests = g_slist_append(s->requests, req); + } + } + +diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h +index 08a2eda..4fffd68 100644 +--- a/tools/qemu-xen/include/sysemu/rng.h ++++ b/tools/qemu-xen/include/sysemu/rng.h +@@ -45,8 +45,7 @@ struct RngBackendClass + { + ObjectClass parent_class; + +- void (*request_entropy)(RngBackend *s, size_t size, +- EntropyReceiveFunc *receive_entropy, void *opaque); ++ void (*request_entropy)(RngBackend *s, RngRequest *req); + void (*cancel_requests)(RngBackend *s); + + void (*opened)(RngBackend *s, Error **errp); +-- +1.7.0.4 + diff --git a/qemu.trad.CVE-2016-1714.patch b/qemu.trad.CVE-2016-1714.patch new file mode 100644 index 0000000..59b840b --- /dev/null +++ b/qemu.trad.CVE-2016-1714.patch @@ -0,0 +1,30 @@ +--- xen-4.6.1/tools/qemu-xen-traditional/hw/fw_cfg.c.orig 2016-01-04 15:35:42.000000000 +0000 ++++ xen-4.6.1/tools/qemu-xen-traditional/hw/fw_cfg.c 2016-03-06 16:42:33.464296362 +0000 +@@ -54,11 +54,15 @@ + static void fw_cfg_write(FWCfgState *s, uint8_t value) + { + int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL); +- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; ++ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL : ++ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; + + FW_CFG_DPRINTF("write %d\n", value); + +- if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) { ++ if (s->cur_entry & FW_CFG_WRITE_CHANNEL ++ && e != NULL ++ && e->callback ++ && s->cur_offset < e->len) { + e->data[s->cur_offset++] = value; + if (s->cur_offset == e->len) { + e->callback(e->callback_opaque, e->data); +@@ -88,7 +92,8 @@ + static uint8_t fw_cfg_read(FWCfgState *s) + { + int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL); +- FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; ++ FWCfgEntry *e = (s->cur_entry == FW_CFG_INVALID) ? NULL : ++ &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK]; + uint8_t ret; + + if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len) diff --git a/qemu.trad.CVE-2016-1981.patch b/qemu.trad.CVE-2016-1981.patch new file mode 100644 index 0000000..cd2a8c1 --- /dev/null +++ b/qemu.trad.CVE-2016-1981.patch @@ -0,0 +1,104 @@ +------------------------------------------------------------------------ +*From*: Laszlo Ersek +*Subject*: [Qemu-devel] [PATCH] e1000: eliminate infinite loops on +out-of-bounds transfer start +*Date*: Tue, 19 Jan 2016 14:17:20 +0100 + +------------------------------------------------------------------------ + +The start_xmit() and e1000_receive_iov() functions implement DMA transfers +iterating over a set of descriptors that the guest's e1000 driver +prepares: + +- the TDLEN and RDLEN registers store the total size of the descriptor + area, + +- while the TDH and RDH registers store the offset (in whole tx / rx + descriptors) into the area where the transfer is supposed to start. + +Each time a descriptor is processed, the TDH and RDH register is bumped +(as appropriate for the transfer direction). + +QEMU already contains logic to deal with bogus transfers submitted by the +guest: + +- Normally, the transmit case wants to increase TDH from its initial value + to TDT. (TDT is allowed to be numerically smaller than the initial TDH + value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe + that QEMU currently has here is a check against reaching the original + TDH value again -- a complete wraparound, which should never happen. + +- In the receive case RDH is increased from its initial value until + "total_size" bytes have been received; preferably in a single step, or + in "s->rxbuf_size" byte steps, if the latter is smaller. However, null + RX descriptors are skipped without receiving data, while RDH is + incremented just the same. QEMU tries to prevent an infinite loop + (processing only null RX descriptors) by detecting whether RDH assumes + its original value during the loop. (Again, wrapping from RDLEN to 0 is + normal.) + +What both directions miss is that the guest could program TDLEN and RDLEN +so low, and the initial TDH and RDH so high, that these registers will +immediately be truncated to zero, and then never reassume their initial +values in the loop -- a full wraparound will never occur. + +The condition that expresses this is: + + xdh_start >= s->mac_reg[XDLEN] / sizeof(desc) + +i.e., TDH or RDH start out after the last whole rx or tx descriptor that +fits into the TDLEN or RDLEN sized area. + +This condition could be checked before we enter the loops, but +pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for +bogus DMA addresses, so we just extend the existing failsafes with the +above condition. + +Cc: "Michael S. Tsirkin" +Cc: Petr Matousek +Cc: Stefano Stabellini +Cc: Prasad Pandit +Cc: Michael Roth +Cc: Jason Wang +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044 +Signed-off-by: Laszlo Ersek +Reviewed-by: Jason Wang +--- + +Notes: + Regarding the public posting: we made an honest effort to vet this + vulnerability, and the impact seems low -- no host side reads/writes, + "just" a DoS (infinite loop). We decided the patch could be posted + publicly, for the usual review process. Jason and Prasad checked the + patch in the internal discussion already, but comments, improvements + etc. are clearly welcome. The CVE request is underway. Thanks. + + hw/net/e1000.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index bec06e9..34d0823 100644 +--- a/tools/qemu-xen-traditional/hw/e1000.c ++++ b/tools/qemu-xen-traditional/hw/e1000.c +@@ -908,7 +908,8 @@ start_xmit(E1000State *s) + * bogus values to TDT/TDLEN. + * there's nothing too intelligent we could do about this. + */ +- if (s->mac_reg[TDH] == tdh_start) { ++ if (s->mac_reg[TDH] == tdh_start || ++ tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) { + DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", + tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); + break; +@@ -1165,7 +1166,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) + s->mac_reg[RDH] = 0; + s->check_rxov = 1; + /* see comment in start_xmit; same here */ +- if (s->mac_reg[RDH] == rdh_start) { ++ if (s->mac_reg[RDH] == rdh_start || ++ rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) { + DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", + rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); + set_ics(s, 0, E1000_ICS_RXO); +-- +1.8.3.1 diff --git a/qemu.trad.CVE-2016-2538.patch b/qemu.trad.CVE-2016-2538.patch new file mode 100644 index 0000000..be05dd7 --- /dev/null +++ b/qemu.trad.CVE-2016-2538.patch @@ -0,0 +1,56 @@ +From: Prasad J Pandit + +When processing remote NDIS control message packets, +the USB Net device emulator uses a fixed length(4096) data buffer. +The incoming informationBufferOffset & Length combination could +overflow and cross that range. Check control message buffer +offsets and length to avoid it. + +Reported-by: Qinghao Tang +Signed-off-by: Prasad J Pandit +--- + hw/usb/dev-network.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +Update as per review + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg03475.html + +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 8a4ff49..180adce 100644 +--- a/tools/qemu-xen-traditional/hw/usb-net.c ++++ b/tools/qemu-xen-traditional/hw/usb-net.c +@@ -915,8 +915,9 @@ static int rndis_query_response(USBNetState *s, + + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8; + buflen = le32_to_cpu(buf->InformationBufferLength); +- if (bufoffs + buflen > length) ++ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) { + return USB_RET_STALL; ++ } + + infobuflen = ndis_query(s, le32_to_cpu(buf->OID), + bufoffs + (uint8_t *) buf, buflen, infobuf, +@@ -961,8 +962,9 @@ static int rndis_set_response(USBNetState *s, + + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8; + buflen = le32_to_cpu(buf->InformationBufferLength); +- if (bufoffs + buflen > length) ++ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) { + return USB_RET_STALL; ++ } + + ret = ndis_set(s, le32_to_cpu(buf->OID), + bufoffs + (uint8_t *) buf, buflen); +@@ -1212,8 +1214,9 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p) + if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) { + uint32_t offs = 8 + le32_to_cpu(msg->DataOffset); + uint32_t size = le32_to_cpu(msg->DataLength); +- if (offs + size <= len) ++ if (offs < len && size < len && offs + size <= len) { + qemu_send_packet(s->vc, s->out_buf + offs, size); ++ } + } + s->out_ptr -= len; + memmove(s->out_buf, &s->out_buf[len], s->out_ptr); +-- +2.5.0 diff --git a/qemu.trad.CVE-2016-2841.patch b/qemu.trad.CVE-2016-2841.patch new file mode 100644 index 0000000..6979fbc --- /dev/null +++ b/qemu.trad.CVE-2016-2841.patch @@ -0,0 +1,34 @@ +From: Prasad J Pandit + +Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152) +bytes to process network packets. Registers PSTART & PSTOP +define ring buffer size & location. Setting these registers +to invalid values could lead to infinite loop or OOB r/w +access issues. Add check to avoid it. + +Reported-by: Yang Hongke +Signed-off-by: Prasad J Pandit +--- + hw/net/ne2000.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Update per review: + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg05522.html + +diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c +index b032212..ced4666 100644 +--- a/tools/qemu-xen-traditional/hw/ne2000.c ++++ b/tools/qemu-xen-traditional/hw/ne2000.c +@@ -154,6 +154,10 @@ static int ne2000_buffer_full(NE2000State *s) + { + int avail, index, boundary; + ++ if (s->stop <= s->start) { ++ return 1; ++ } ++ + index = s->curpag << 8; + boundary = s->boundary << 8; + if (index < boundary) +-- +2.5.0 diff --git a/qemu.trad.CVE-2016-2857.patch b/qemu.trad.CVE-2016-2857.patch new file mode 100644 index 0000000..5bef1a7 --- /dev/null +++ b/qemu.trad.CVE-2016-2857.patch @@ -0,0 +1,45 @@ +From: Prasad J Pandit + +While computing IP checksum, 'net_checksum_calculate' reads +payload length from the packet. It could exceed the given 'data' +buffer size. Add a check to avoid it. + +Reported-by: Liu Ling +Signed-off-by: Prasad J Pandit +--- + net/checksum.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +Update as per review: + -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg06121.html + +diff --git a/net/checksum.c b/net/checksum.c +index 14c0855..0942437 100644 +--- a/tools/qemu-xen-traditional/net-checksum.c ++++ b/tools/qemu-xen-traditional/net-checksum.c +@@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length) + int hlen, plen, proto, csum_offset; + uint16_t csum; + ++ /* Ensure data has complete L2 & L3 headers. */ ++ if (length < 14 + 20) { ++ return; ++ } ++ + if ((data[14] & 0xf0) != 0x40) + return; /* not IPv4 */ + hlen = (data[14] & 0x0f) * 4; +@@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length) + return; + } + +- if (plen < csum_offset+2) +- return; ++ if (plen < csum_offset + 2 || 14 + hlen + plen > length) { ++ return; ++ } + + data[14+hlen+csum_offset] = 0; + data[14+hlen+csum_offset+1] = 0; +-- +2.5.0 diff --git a/xen.spec b/xen.spec index 7247c16..7b50f84 100644 --- a/xen.spec +++ b/xen.spec @@ -51,7 +51,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.5.2 -Release: 8%{?dist} +Release: 9%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -131,6 +131,24 @@ Patch62: qemu.git-aa4a3dce1c88ed51b616806b8214b7c8428b7470.patch Patch63: qemu.git-aa7f9966dfdff500bbbf1956d9e115b1fa8987a6.patch Patch64: xsa154-4.5.patch Patch65: xsa170-4.5.patch +Patch66: qemu.trad.CVE-2016-1714.patch +Patch67: qemu.CVE-2016-1922.patch +Patch68: qemu.CVE-2015-8613.patch +Patch69: qemu.CVE-2016-1981.patch +Patch70: qemu.trad.CVE-2016-1981.patch +Patch71: qemu.bug1300235.patch +Patch72: qemu.CVE-2016-2198.patch +Patch73: qemu.CVE-2016-2841.patch +Patch74: qemu.trad.CVE-2016-2841.patch +Patch75: qemu.CVE-2016-2538.patch +Patch76: qemu.trad.CVE-2016-2538.patch +Patch77: qemu.CVE-2016-2392.patch +Patch78: qemu.CVE-2016-2391.patch +Patch79: qemu.CVE-2016-2857.patch +Patch80: qemu.trad.CVE-2016-2857.patch +Patch81: qemu.CVE-2015-8817+8.patch +Patch82: qemu.git-60253ed1e6ec6d8e5ef2efe7bf755f475.patch +Patch83: qemu.CVE-2016-1714.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -364,6 +382,24 @@ manage Xen virtual machines. %patch63 -p1 %patch64 -p1 %patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 # stubdom sources cp -v %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} %{SOURCE15} stubdom @@ -887,6 +923,32 @@ rm -rf %{buildroot} %endif %changelog +* Mon Mar 07 2016 Michael Young - 4.5.2-9 +- Qemu: nvram: OOB r/w access in processing firmware configurations + CVE-2016-1714 (#1296080) +- Qemu: i386: null pointer dereference in vapic_write() CVE-2016-1922 + (#1292767) +- qemu: Stack-based buffer overflow in megasas_ctrl_get_info CVE-2015-8613 + (#1293305) +- qemu-kvm: Infinite loop and out-of-bounds transfer start in start_xmit() + and e1000_receive_iov() CVE-2016-1981 (#1299996) +- Qemu: usb ehci out-of-bounds read in ehci_process_itd (#1300235) +- Qemu: usb: ehci null pointer dereference in ehci_caps_write CVE-2016-2198 + (#1303135) +- Qemu: net: ne2000: infinite loop in ne2000_receive CVE-2016-2841 (#1304048) +- Qemu: usb: integer overflow in remote NDIS control message handling + CVE-2016-2538 (#1305816) +- Qemu: usb: null pointer dereference in remote NDIS control message handling + CVE-2016-2392 (#1307116) +- Qemu: usb: multiple eof_timers in ohci module leads to null pointer + dereference CVE-2016-2391 (#1308882) +- Qemu: net: out of bounds read in net_checksum_calculate() CVE-2016-2857 + (#1309565) +- Qemu: OOB access in address_space_rw leads to segmentation fault + CVE-2015-8817 CVE-2015-8818 (#1313273) +- Qemu: rng-random: arbitrary stack based allocation leading to corruption + CVE-2016-2858 (#1314678) + * Wed Feb 17 2016 Michael Young - 4.5.2-8 - x86: inconsistent cachability flags on guest mappings [XSA-154, CVE-2016-2270] (#1309324)