[pve-devel] [stable-3 kvm] various fixes:

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Feb 9 09:06:57 CET 2016


CVE-2016-1568: ide: ahci: reset ncq object to unused on error
CVE-2015-3209: pcnet: force the buffer access to be in bounds during tx
CVE-2015-7504: net: pcnet: add check to validate receive data size
CVE-2015-7512: pcnet: fix rx buffer overflow
CVE-2015-7295: 3 patches:
   virtio: introduce virtqueue_unmap_sg()
   virtio: introduce virtqueue_discard()
   virtio-net: correctly drop truncated packets
---
 debian/patches/CVE-2015-3209-pcnet-oob.patch       |  49 +++++++
 ...-7295-virtio-introduce-virtqueue_unmap_sg.patch | 153 +++++++++++++++++++++
 .../CVE-2015-7504-pcnet-validate-size.patch        |  49 +++++++
 .../CVE-2015-7512-pcnet-rx-buffer-overflow.patch   |  37 +++++
 .../CVE-2016-1568-ide-ahci-reset-ncq-object.patch  |  62 +++++++++
 debian/patches/series                              |   5 +
 6 files changed, 355 insertions(+)
 create mode 100644 debian/patches/CVE-2015-3209-pcnet-oob.patch
 create mode 100644 debian/patches/CVE-2015-7295-virtio-introduce-virtqueue_unmap_sg.patch
 create mode 100644 debian/patches/CVE-2015-7504-pcnet-validate-size.patch
 create mode 100644 debian/patches/CVE-2015-7512-pcnet-rx-buffer-overflow.patch
 create mode 100644 debian/patches/CVE-2016-1568-ide-ahci-reset-ncq-object.patch

diff --git a/debian/patches/CVE-2015-3209-pcnet-oob.patch b/debian/patches/CVE-2015-3209-pcnet-oob.patch
new file mode 100644
index 0000000..53b0979
--- /dev/null
+++ b/debian/patches/CVE-2015-3209-pcnet-oob.patch
@@ -0,0 +1,49 @@
+From 9f7c594c006289ad41169b854d70f5da6e400a2a Mon Sep 17 00:00:00 2001
+From: Petr Matousek <pmatouse at redhat.com>
+Date: Sun, 24 May 2015 10:53:44 +0200
+Subject: [PATCH] pcnet: force the buffer access to be in bounds during tx
+
+4096 is the maximum length per TMD and it is also currently the size of
+the relay buffer pcnet driver uses for sending the packet data to QEMU
+for further processing. With packet spanning multiple TMDs it can
+happen that the overall packet size will be bigger than sizeof(buffer),
+which results in memory corruption.
+
+Fix this by only allowing to queue maximum sizeof(buffer) bytes.
+
+This is CVE-2015-3209.
+
+[Fixed 3-space indentation to QEMU's 4-space coding standard.
+--Stefan]
+
+Signed-off-by: Petr Matousek <pmatouse at redhat.com>
+Reported-by: Matt Tait <matttait at google.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
+---
+ hw/net/pcnet.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
+index bdfd38f..68b9981 100644
+--- a/hw/net/pcnet.c
++++ b/hw/net/pcnet.c
+@@ -1241,6 +1241,14 @@ static void pcnet_transmit(PCNetState *s)
+         }
+ 
+         bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
++
++        /* if multi-tmd packet outsizes s->buffer then skip it silently.
++           Note: this is not what real hw does */
++        if (s->xmit_pos + bcnt > sizeof(s->buffer)) {
++            s->xmit_pos = -1;
++            goto txdone;
++        }
++
+         s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+                          s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+         s->xmit_pos += bcnt;
+-- 
+2.1.4
+
diff --git a/debian/patches/CVE-2015-7295-virtio-introduce-virtqueue_unmap_sg.patch b/debian/patches/CVE-2015-7295-virtio-introduce-virtqueue_unmap_sg.patch
new file mode 100644
index 0000000..e73e1c0
--- /dev/null
+++ b/debian/patches/CVE-2015-7295-virtio-introduce-virtqueue_unmap_sg.patch
@@ -0,0 +1,153 @@
+From ce317461573bac12b10d67699b4ddf1f97cf066c Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang at redhat.com>
+Date: Fri, 25 Sep 2015 13:21:28 +0800
+Subject: [PATCH 1/3] virtio: introduce virtqueue_unmap_sg()
+
+Factor out sg unmapping logic. This will be reused by the patch that
+can discard descriptor.
+
+Cc: Michael S. Tsirkin <mst at redhat.com>
+Cc: Andrew James <andrew.james at hpe.com>
+Signed-off-by: Jason Wang <jasowang at redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+---
+ hw/virtio/virtio.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 7504f8b..6f2b96c 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -244,14 +244,12 @@ int virtio_queue_empty(VirtQueue *vq)
+     return vring_avail_idx(vq) == vq->last_avail_idx;
+ }
+ 
+-void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+-                    unsigned int len, unsigned int idx)
++static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
++                               unsigned int len)
+ {
+     unsigned int offset;
+     int i;
+ 
+-    trace_virtqueue_fill(vq, elem, len, idx);
+-
+     offset = 0;
+     for (i = 0; i < elem->in_num; i++) {
+         size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
+@@ -267,6 +265,14 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+         cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
+                                   elem->out_sg[i].iov_len,
+                                   0, elem->out_sg[i].iov_len);
++}
++
++void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
++                    unsigned int len, unsigned int idx)
++{
++    trace_virtqueue_fill(vq, elem, len, idx);
++
++    virtqueue_unmap_sg(vq, elem, len);
+ 
+     idx = (idx + vring_used_idx(vq)) % vq->vring.num;
+ 
+-- 
+2.1.4
+
+From 29b9f5efd78ae0f9cc02dd169b6e80d2c404bade Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang at redhat.com>
+Date: Fri, 25 Sep 2015 13:21:29 +0800
+Subject: [PATCH 2/3] virtio: introduce virtqueue_discard()
+
+This patch introduces virtqueue_discard() to discard a descriptor and
+unmap the sgs. This will be used by the patch that will discard
+descriptor when packet is truncated.
+
+Cc: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Jason Wang <jasowang at redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+---
+ hw/virtio/virtio.c         | 7 +++++++
+ include/hw/virtio/virtio.h | 2 ++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 6f2b96c..d0bc72e 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -267,6 +267,13 @@ static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
+                                   0, elem->out_sg[i].iov_len);
+ }
+ 
++void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
++                       unsigned int len)
++{
++    vq->last_avail_idx--;
++    virtqueue_unmap_sg(vq, elem, len);
++}
++
+ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+                     unsigned int len, unsigned int idx)
+ {
+diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
+index 6201ee8..9d09115 100644
+--- a/include/hw/virtio/virtio.h
++++ b/include/hw/virtio/virtio.h
+@@ -146,6 +146,8 @@ void virtio_del_queue(VirtIODevice *vdev, int n);
+ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
+                     unsigned int len);
+ void virtqueue_flush(VirtQueue *vq, unsigned int count);
++void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
++                       unsigned int len);
+ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+                     unsigned int len, unsigned int idx);
+ 
+-- 
+2.1.4
+
+From 0cf33fb6b49a19de32859e2cdc6021334f448fb3 Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang at redhat.com>
+Date: Fri, 25 Sep 2015 13:21:30 +0800
+Subject: [PATCH 3/3] virtio-net: correctly drop truncated packets
+
+When packet is truncated during receiving, we drop the packets but
+neither discard the descriptor nor add and signal used
+descriptor. This will lead several issues:
+
+- sg mappings are leaked
+- rx will be stalled if a lots of packets were truncated
+
+In order to be consistent with vhost, fix by discarding the descriptor
+in this case.
+
+Cc: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Jason Wang <jasowang at redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+---
+ hw/net/virtio-net.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index d388c55..a877614 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1094,13 +1094,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
+          * must have consumed the complete packet.
+          * Otherwise, drop it. */
+         if (!n->mergeable_rx_bufs && offset < size) {
+-#if 0
+-            error_report("virtio-net truncated non-mergeable packet: "
+-                         "i %zd mergeable %d offset %zd, size %zd, "
+-                         "guest hdr len %zd, host hdr len %zd",
+-                         i, n->mergeable_rx_bufs,
+-                         offset, size, n->guest_hdr_len, n->host_hdr_len);
+-#endif
++            virtqueue_discard(q->rx_vq, &elem, total);
+             return size;
+         }
+ 
+-- 
+2.1.4
+
diff --git a/debian/patches/CVE-2015-7504-pcnet-validate-size.patch b/debian/patches/CVE-2015-7504-pcnet-validate-size.patch
new file mode 100644
index 0000000..5c5874e
--- /dev/null
+++ b/debian/patches/CVE-2015-7504-pcnet-validate-size.patch
@@ -0,0 +1,49 @@
+From 837f21aacf5a714c23ddaadbbc5212f9b661e3f7 Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp at fedoraproject.org>
+Date: Fri, 20 Nov 2015 11:50:31 +0530
+Subject: [PATCH] net: pcnet: add check to validate receive data
+ size(CVE-2015-7504)
+
+In loopback mode, pcnet_receive routine appends CRC code to the
+receive buffer. If the data size given is same as the buffer size,
+the appended CRC code overwrites 4 bytes after s->buffer. Added a
+check to avoid that.
+
+Reported by: Qinghao Tang <luodalongde at gmail.com>
+Cc: qemu-stable at nongnu.org
+Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Prasad J Pandit <pjp at fedoraproject.org>
+Signed-off-by: Jason Wang <jasowang at redhat.com>
+---
+ hw/net/pcnet.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
+index 0eb3cc4..309c40b 100644
+--- a/hw/net/pcnet.c
++++ b/hw/net/pcnet.c
+@@ -1084,7 +1084,7 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
+                 uint32_t fcs = ~0;
+                 uint8_t *p = src;
+ 
+-                while (p != &src[size-4])
++                while (p != &src[size])
+                     CRC(fcs, *p++);
+                 crc_err = (*(uint32_t *)p != htonl(fcs));
+             }
+@@ -1233,8 +1233,10 @@ static void pcnet_transmit(PCNetState *s)
+         bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+ 
+         /* if multi-tmd packet outsizes s->buffer then skip it silently.
+-           Note: this is not what real hw does */
+-        if (s->xmit_pos + bcnt > sizeof(s->buffer)) {
++         * Note: this is not what real hw does.
++         * Last four bytes of s->buffer are used to store CRC FCS code.
++         */
++        if (s->xmit_pos + bcnt > sizeof(s->buffer) - 4) {
+             s->xmit_pos = -1;
+             goto txdone;
+         }
+-- 
+2.1.4
+
diff --git a/debian/patches/CVE-2015-7512-pcnet-rx-buffer-overflow.patch b/debian/patches/CVE-2015-7512-pcnet-rx-buffer-overflow.patch
new file mode 100644
index 0000000..e33a3b2
--- /dev/null
+++ b/debian/patches/CVE-2015-7512-pcnet-rx-buffer-overflow.patch
@@ -0,0 +1,37 @@
+From 8b98a2f07175d46c3f7217639bd5e03f2ec56343 Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang at redhat.com>
+Date: Mon, 30 Nov 2015 15:00:06 +0800
+Subject: [PATCH] pcnet: fix rx buffer overflow(CVE-2015-7512)
+
+Backends could provide a packet whose length is greater than buffer
+size. Check for this and truncate the packet to avoid rx buffer
+overflow in this case.
+
+Cc: Prasad J Pandit <pjp at fedoraproject.org>
+Cc: qemu-stable at nongnu.org
+Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Jason Wang <jasowang at redhat.com>
+---
+ hw/net/pcnet.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
+index 309c40b..1f4a3db 100644
+--- a/hw/net/pcnet.c
++++ b/hw/net/pcnet.c
+@@ -1064,6 +1064,12 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
+             int pktcount = 0;
+ 
+             if (!s->looptest) {
++                if (size > 4092) {
++#ifdef PCNET_DEBUG_RMD
++                    fprintf(stderr, "pcnet: truncates rx packet.\n");
++#endif
++                    size = 4092;
++                }
+                 memcpy(src, buf, size);
+                 /* no need to compute the CRC */
+                 src[size] = 0;
+-- 
+2.1.4
+
diff --git a/debian/patches/CVE-2016-1568-ide-ahci-reset-ncq-object.patch b/debian/patches/CVE-2016-1568-ide-ahci-reset-ncq-object.patch
new file mode 100644
index 0000000..d157819
--- /dev/null
+++ b/debian/patches/CVE-2016-1568-ide-ahci-reset-ncq-object.patch
@@ -0,0 +1,62 @@
+From 4ab0359a8ae182a7ac5c99609667273167703fab Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp at fedoraproject.org>
+Date: Mon, 11 Jan 2016 14:10:42 -0500
+Subject: [PATCH] ide: ahci: reset ncq object to unused on error
+
+When processing NCQ commands, AHCI device emulation prepares a
+NCQ transfer object; To which an aio control block(aiocb) object
+is assigned in 'execute_ncq_command'. In case, when the NCQ
+command is invalid, the 'aiocb' object is not assigned, and NCQ
+transfer object is left as 'used'. This leads to a use after
+free kind of error in 'bdrv_aio_cancel_async' via 'ahci_reset_port'.
+Reset NCQ transfer object to 'unused' to avoid it.
+
+[Maintainer edit: s/ACHI/AHCI/ in the commit message. --js]
+
+Reported-by: Qinghao Tang <luodalongde at gmail.com>
+Signed-off-by: Prasad J Pandit <pjp at fedoraproject.org>
+Reviewed-by: John Snow <jsnow at redhat.com>
+Message-id: 1452282511-4116-1-git-send-email-ppandit at redhat.com
+Signed-off-by: John Snow <jsnow at redhat.com>
+---
+ hw/ide/ahci.c | 1 +
+ 1 file changed, 1 insertion(+)
+#     ide_state->error = ABRT_ERR;
+#     ide_state->status = READY_STAT | ERR_STAT;
+#     ncq_tfs->drive->port_regs.scr_err |= (1 << ncq_tfs->tag);
+#+    ncq_tfs->used = 0;
+# }
+# 
+# static void ncq_finish(NCQTransferState *ncq_tfs)
+--
+From Debian:
+  Mjt:
+  
+  In 2.1, the code is different.  In particular, execute_ncq_command()
+  is part of process_ncq_command(), and there's no ncq_err() function
+  yet.  We do the "used = 0" assignment in the exact place where the
+  invalid NCQ command is detected.
+#         default:
+#             DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n");
+#             qemu_sglist_destroy(&ncq_tfs->sglist);
+#+            ncq_tfs->used = 0;
+#             break;
+#     }
+# }
+--
+  In 2.2 the DPRINTF is split in two:
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index dd1912e..17f1cbd 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -910,6 +910,7 @@ static void ncq_err(NCQTransferState *ncq_tfs)
+                         "error: tried to process non-NCQ command as NCQ\n");
+             }
+             qemu_sglist_destroy(&ncq_tfs->sglist);
++            ncq_tfs->used = 0;
+     }
+ }
+ 
+-- 
+2.1.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 63b656a..2d3bceb 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -54,3 +54,8 @@ CVE-2015-8619-hmp-sendkey-oob-fix.patch
 CVE-2016-1714-fw_cfg-add-check-to-validate-current-entry.patch
 CVE-2016-1922-i386-avoid-null-pointer-dereference.patch
 CVE-2016-1981-e1000-eliminate-infinite-loop.patch
+CVE-2016-1568-ide-ahci-reset-ncq-object.patch
+CVE-2015-3209-pcnet-oob.patch
+CVE-2015-7504-pcnet-validate-size.patch
+CVE-2015-7512-pcnet-rx-buffer-overflow.patch
+CVE-2015-7295-virtio-introduce-virtqueue_unmap_sg.patch
-- 
2.1.4





More information about the pve-devel mailing list