diff options
author | Matthias Maier <tamiko@gentoo.org> | 2017-02-20 21:27:40 -0600 |
---|---|---|
committer | Matthias Maier <tamiko@gentoo.org> | 2017-02-21 06:03:08 -0600 |
commit | cc47fc6cf1fef191ebb6c19d4b8bba9a12294024 (patch) | |
tree | afc4ec33a7912349a8fcf51816d6a42b6af853c9 /app-emulation/qemu/files | |
parent | app-emulation/qemu: drop old (diff) | |
download | gentoo-cc47fc6cf1fef191ebb6c19d4b8bba9a12294024.tar.gz gentoo-cc47fc6cf1fef191ebb6c19d4b8bba9a12294024.tar.bz2 gentoo-cc47fc6cf1fef191ebb6c19d4b8bba9a12294024.zip |
app-emulation/qemu: security fixes, notably CVE-2017-2620, bug #609206
This commit applies a number of patches fixing
CVE-2017-2620 #609206
CVE-2017-2630 #609396
CVE-2017-5973 #609334
CVE-2017-5987 #609398
CVE-2017-6058 #609638
Package-Manager: Portage-2.3.3, Repoman-2.3.1
Diffstat (limited to 'app-emulation/qemu/files')
5 files changed, 327 insertions, 0 deletions
diff --git a/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2620.patch b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2620.patch new file mode 100644 index 000000000000..e2a98012d7cc --- /dev/null +++ b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2620.patch @@ -0,0 +1,56 @@ +From: Gerd Hoffmann <kraxel@redhat.com> +Subject: [PATCH 3/3] cirrus: add blit_is_unsafe call to cirrus_bitblt_cputovideo + +CIRRUS_BLTMODE_MEMSYSSRC blits do NOT check blit destination +and blit width, at all. Oops. Fix it. + +Security impact: high. + +The missing blit destination check allows to write to host memory. +Basically same as CVE-2014-8106 for the other blit variants. + +The missing blit width check allows to overflow cirrus_bltbuf, +with the attractive target cirrus_srcptr (current cirrus_bltbuf write +position) being located right after cirrus_bltbuf in CirrusVGAState. + +Due to cirrus emulation writing cirrus_bltbuf bytewise the attacker +hasn't full control over cirrus_srcptr though, only one byte can be +changed. Once the first byte has been modified further writes land +elsewhere. + +[ This is CVE-2017-2620 / XSA-209 - Ian Jackson ] + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index 0e47cf8..a093dc8 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -899,6 +899,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) + { + int w; + ++ if (blit_is_unsafe(s)) { ++ return 0; ++ } ++ + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; +@@ -924,6 +928,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; + } ++ ++ /* the blit_is_unsafe call above should catch this */ ++ assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE); ++ + s->cirrus_srcptr = s->cirrus_bltbuf; + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + cirrus_update_memory_access(s); +-- +1.8.3.1 + diff --git a/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2630.patch b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2630.patch new file mode 100644 index 000000000000..034b322de5f9 --- /dev/null +++ b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-2630.patch @@ -0,0 +1,22 @@ +Comparison symbol is misused. It may lead to memory corruption. + +Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden> +--- + nbd/client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nbd/client.c b/nbd/client.c +index 6caf6bda6d..351731bc63 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -94,7 +94,7 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size) + char small[1024]; + char *buffer; + +- buffer = sizeof(small) < size ? small : g_malloc(MIN(65536, size)); ++ buffer = sizeof(small) > size ? small : g_malloc(MIN(65536, size)); + while (size > 0) { + ssize_t count = read_sync(ioc, buffer, MIN(65536, size)); + +-- +2.11.0 diff --git a/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5973.patch b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5973.patch new file mode 100644 index 000000000000..50ff3c997924 --- /dev/null +++ b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5973.patch @@ -0,0 +1,87 @@ +Limits should be big enough that normal guest should not hit it. +Add a tracepoint to log them, just in case. Also, while being +at it, log the existing link trb limit too. + +Reported-by: 李强 <address@hidden> +Signed-off-by: Gerd Hoffmann <address@hidden> +--- + hw/usb/hcd-xhci.c | 15 ++++++++++++++- + hw/usb/trace-events | 1 + + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index fbf8a8b..28dd2f2 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -51,6 +51,8 @@ + #define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) + + #define TRB_LINK_LIMIT 4 ++#define COMMAND_LIMIT 256 ++#define TRANSFER_LIMIT 256 + + #define LEN_CAP 0x40 + #define LEN_OPER (0x400 + 0x10 * MAXPORTS) +@@ -943,6 +945,7 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, + return type; + } else { + if (++link_cnt > TRB_LINK_LIMIT) { ++ trace_usb_xhci_enforced_limit("trb-link"); + return 0; + } + ring->dequeue = xhci_mask64(trb->parameter); +@@ -2060,6 +2063,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) + XHCIRing *ring; + USBEndpoint *ep = NULL; + uint64_t mfindex; ++ unsigned int count = 0; + int length; + int i; + +@@ -2172,6 +2176,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) + epctx->retry = xfer; + break; + } ++ if (count++ > TRANSFER_LIMIT) { ++ trace_usb_xhci_enforced_limit("transfers"); ++ break; ++ } + } + epctx->kick_active--; + +@@ -2618,7 +2626,7 @@ static void xhci_process_commands(XHCIState *xhci) + TRBType type; + XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS}; + dma_addr_t addr; +- unsigned int i, slotid = 0; ++ unsigned int i, slotid = 0, count = 0; + + DPRINTF("xhci_process_commands()\n"); + if (!xhci_running(xhci)) { +@@ -2735,6 +2743,11 @@ static void xhci_process_commands(XHCIState *xhci) + } + event.slotid = slotid; + xhci_event(xhci, &event, 0); ++ ++ if (count++ > COMMAND_LIMIT) { ++ trace_usb_xhci_enforced_limit("commands"); ++ return; ++ } + } + } + +diff --git a/hw/usb/trace-events b/hw/usb/trace-events +index fdd1d29..0c323d4 100644 +--- a/hw/usb/trace-events ++++ b/hw/usb/trace-events +@@ -174,6 +174,7 @@ usb_xhci_xfer_retry(void *xfer) "%p" + usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d" + usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d" + usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)" ++usb_xhci_enforced_limit(const char *item) "%s" + + # hw/usb/desc.c + usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" +-- +1.8.3.1 + diff --git a/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5987.patch b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5987.patch new file mode 100644 index 000000000000..bfde2e9d4b78 --- /dev/null +++ b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-5987.patch @@ -0,0 +1,50 @@ +From: Prasad J Pandit <address@hidden> + +In the SDHCI protocol, the transfer mode register value +is used during multi block transfer to check if block count +register is enabled and should be updated. Transfer mode +register could be set such that, block count register would +not be updated, thus leading to an infinite loop. Add check +to avoid it. + +Reported-by: Wjjzhang <address@hidden> +Reported-by: Jiang Xin <address@hidden> +Signed-off-by: Prasad J Pandit <address@hidden> +--- + hw/sd/sdhci.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +Update: use qemu_log_mask(LOG_UNIMP, ...) + -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02354.html + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 5bd5ab6..a9c744b 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -486,6 +486,11 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) + uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12); + uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk); + ++ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) { ++ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n"); ++ return; ++ } ++ + /* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for + * possible stop at page boundary if initial address is not page aligned, + * allow them to work properly */ +@@ -797,11 +802,6 @@ static void sdhci_data_transfer(void *opaque) + if (s->trnmod & SDHC_TRNS_DMA) { + switch (SDHC_DMA_TYPE(s->hostctl)) { + case SDHC_CTRL_SDMA: +- if ((s->trnmod & SDHC_TRNS_MULTI) && +- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) { +- break; +- } +- + if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) { + sdhci_sdma_transfer_single_block(s); + } else { +-- +2.9.3 + diff --git a/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-6058.patch b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-6058.patch new file mode 100644 index 000000000000..666c18ccea17 --- /dev/null +++ b/app-emulation/qemu/files/qemu-2.8.0-CVE-2017-6058.patch @@ -0,0 +1,112 @@ +This patch fixed a problem that was introduced in commit eb700029. + +When net_rx_pkt_attach_iovec() calls eth_strip_vlan() +this can result in pkt->ehdr_buf being overflowed, because +ehdr_buf is only sizeof(struct eth_header) bytes large +but eth_strip_vlan() can write +sizeof(struct eth_header) + sizeof(struct vlan_header) +bytes into it. + +Devices affected by this problem: vmxnet3. + +Reported-by: Peter Maydell <address@hidden> +Signed-off-by: Dmitry Fleytman <address@hidden> +--- + hw/net/net_rx_pkt.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c +index 1019b50..7c0beac 100644 +--- a/hw/net/net_rx_pkt.c ++++ b/hw/net/net_rx_pkt.c +@@ -23,13 +23,13 @@ + + struct NetRxPkt { + struct virtio_net_hdr virt_hdr; +- uint8_t ehdr_buf[sizeof(struct eth_header)]; ++ uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)]; + struct iovec *vec; + uint16_t vec_len_total; + uint16_t vec_len; + uint32_t tot_len; + uint16_t tci; +- bool vlan_stripped; ++ size_t ehdr_buf_len; + bool has_virt_hdr; + eth_pkt_types_e packet_type; + +@@ -88,15 +88,13 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt, + const struct iovec *iov, int iovcnt, + size_t ploff) + { +- if (pkt->vlan_stripped) { ++ if (pkt->ehdr_buf_len) { + net_rx_pkt_iovec_realloc(pkt, iovcnt + 1); + + pkt->vec[0].iov_base = pkt->ehdr_buf; +- pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf); +- +- pkt->tot_len = +- iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header); ++ pkt->vec[0].iov_len = pkt->ehdr_buf_len; + ++ pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len; + pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1, + iov, iovcnt, ploff, pkt->tot_len); + } else { +@@ -123,11 +121,12 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt, + uint16_t tci = 0; + uint16_t ploff = iovoff; + assert(pkt); +- pkt->vlan_stripped = false; + + if (strip_vlan) { +- pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf, +- &ploff, &tci); ++ pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf, ++ &ploff, &tci); ++ } else { ++ pkt->ehdr_buf_len = 0; + } + + pkt->tci = tci; +@@ -143,12 +142,13 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt, + uint16_t tci = 0; + uint16_t ploff = iovoff; + assert(pkt); +- pkt->vlan_stripped = false; + + if (strip_vlan) { +- pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet, +- pkt->ehdr_buf, +- &ploff, &tci); ++ pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet, ++ pkt->ehdr_buf, ++ &ploff, &tci); ++ } else { ++ pkt->ehdr_buf_len = 0; + } + + pkt->tci = tci; +@@ -162,8 +162,8 @@ void net_rx_pkt_dump(struct NetRxPkt *pkt) + NetRxPkt *pkt = (NetRxPkt *)pkt; + assert(pkt); + +- printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n", +- pkt->tot_len, pkt->vlan_stripped, pkt->tci); ++ printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n", ++ pkt->tot_len, pkt->ehdr_buf_len, pkt->tci); + #endif + } + +@@ -426,7 +426,7 @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt) + { + assert(pkt); + +- return pkt->vlan_stripped; ++ return pkt->ehdr_buf_len ? true : false; + } + + bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt) +-- +2.7.4 |