diff -u qemu-kvm-1.0+noroms/debian/changelog qemu-kvm-1.0+noroms/debian/changelog --- qemu-kvm-1.0+noroms/debian/changelog +++ qemu-kvm-1.0+noroms/debian/changelog @@ -1,3 +1,19 @@ +qemu-kvm (1.0+noroms-0ubuntu14.29) precise-security; urgency=medium + + * SECURITY UPDATE: infinite loop in vmware_vga + - debian/patches/CVE-2016-4453.patch: limit fifo commands in + hw/vmware_vga.c. + - CVE-2016-4453 + * SECURITY UPDATE: DoS or host memory leakage in vmware_vga + - debian/patches/CVE-2016-4454.patch: fix sanity checks in + hw/vmware_vga.c. + - CVE-2016-4454 + * SECURITY UPDATE: DoS via unbounded memory allocation + - debian/patches/CVE-2016-5403.patch: check size in hw/virtio.c. + - CVE-2016-5403 + + -- Marc Deslauriers Thu, 04 Aug 2016 07:50:42 -0400 + qemu-kvm (1.0+noroms-0ubuntu14.28) precise-security; urgency=medium * SECURITY UPDATE: denial of service via multiple eof_timers in ohci diff -u qemu-kvm-1.0+noroms/debian/patches/series qemu-kvm-1.0+noroms/debian/patches/series --- qemu-kvm-1.0+noroms/debian/patches/series +++ qemu-kvm-1.0+noroms/debian/patches/series @@ -104,0 +105,3 @@ +CVE-2016-4454.patch +CVE-2016-4453.patch +CVE-2016-5403.patch only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/CVE-2016-5403.patch +++ qemu-kvm-1.0+noroms/debian/patches/CVE-2016-5403.patch @@ -0,0 +1,64 @@ +Backport of: + +From afd9096eb1882f23929f5b5c177898ed231bac66 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 19 Jul 2016 13:07:13 +0100 +Subject: [PATCH] virtio: error out if guest exceeds virtqueue size + +A broken or malicious guest can submit more requests than the virtqueue +size permits, causing unbounded memory allocation in QEMU. + +The guest can submit requests without bothering to wait for completion +and is therefore not bound by virtqueue size. This requires reusing +vring descriptors in more than one request, which is not allowed by the +VIRTIO 1.0 specification. + +In "3.2.1 Supplying Buffers to The Device", the VIRTIO 1.0 specification +says: + + 1. The driver places the buffer into free descriptor(s) in the + descriptor table, chaining as necessary + +and + + Note that the above code does not take precautions against the + available ring buffer wrapping around: this is not possible since the + ring buffer is the same size as the descriptor table, so step (1) will + prevent such a condition. + +This implies that placing more buffers into the virtqueue than the +descriptor table size is not allowed. + +QEMU is missing the check to prevent this case. Processing a request +allocates a VirtQueueElement leading to unbounded memory allocation +controlled by the guest. + +Exit with an error if the guest provides more requests than the +virtqueue size permits. This bounds memory allocation and makes the +buggy guest visible to the user. + +This patch fixes CVE-2016-5403 and was reported by Zhenhao Hong from 360 +Marvel Team, China. + +Reported-by: Zhenhao Hong +Signed-off-by: Stefan Hajnoczi +--- + hw/virtio/virtio.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +Index: qemu-kvm-1.0+noroms/hw/virtio.c +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/virtio.c 2016-08-04 07:46:10.853064092 -0400 ++++ qemu-kvm-1.0+noroms/hw/virtio.c 2016-08-04 07:46:10.849064058 -0400 +@@ -452,6 +452,11 @@ + + max = vq->vring.num; + ++ if (vq->inuse >= vq->vring.num) { ++ error_report("Virtqueue size exceeded"); ++ exit(1); ++ } ++ + i = head = virtqueue_get_head(vq, vq->last_avail_idx++); + if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + vring_avail_event(vq, vring_avail_idx(vq)); only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/CVE-2016-4454.patch +++ qemu-kvm-1.0+noroms/debian/patches/CVE-2016-4454.patch @@ -0,0 +1,135 @@ +Description: fix DoS or host memory leak in vmware_vga +Origin: backport, http://git.qemu.org/?p=qemu.git;a=commit;h=521360267876d3b6518b328051a2e56bca55bef8 +Origin: backport, http://git.qemu.org/?p=qemu.git;a=commit;h=c2e3c54d3960bc53bfa3a5ce7ea7a050b9be267e +Origin: backport, http://git.qemu.org/?p=qemu.git;a=commit;h=7e486f7577764a07aa35588e119903c80a5c30a2 + +Index: qemu-kvm-1.0+noroms/hw/vmware_vga.c +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/vmware_vga.c 2016-08-04 07:35:54.960012574 -0400 ++++ qemu-kvm-1.0+noroms/hw/vmware_vga.c 2016-08-04 07:38:42.733387728 -0400 +@@ -68,17 +68,11 @@ + uint8_t *fifo_ptr; + unsigned int fifo_size; + +- union { +- uint32_t *fifo; +- struct QEMU_PACKED { +- uint32_t min; +- uint32_t max; +- uint32_t next_cmd; +- uint32_t stop; +- /* Add registers here when adding capabilities. */ +- uint32_t fifo[0]; +- } *cmd; +- }; ++ uint32_t *fifo; ++ uint32_t fifo_min; ++ uint32_t fifo_max; ++ uint32_t fifo_next; ++ uint32_t fifo_stop; + + #define REDRAW_FIFO_LEN 512 + struct vmsvga_rect_s { +@@ -192,7 +186,7 @@ + */ + SVGA_FIFO_MIN = 0, + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ +- SVGA_FIFO_NEXT_CMD, ++ SVGA_FIFO_NEXT, + SVGA_FIFO_STOP, + + /* +@@ -542,25 +536,49 @@ + } + #endif + +-#define CMD(f) le32_to_cpu(s->cmd->f) +- + static inline int vmsvga_fifo_length(struct vmsvga_state_s *s) + { + int num; + if (!s->config || !s->enable) + return 0; +- num = CMD(next_cmd) - CMD(stop); ++ ++ s->fifo_min = le32_to_cpu(s->fifo[SVGA_FIFO_MIN]); ++ s->fifo_max = le32_to_cpu(s->fifo[SVGA_FIFO_MAX]); ++ s->fifo_next = le32_to_cpu(s->fifo[SVGA_FIFO_NEXT]); ++ s->fifo_stop = le32_to_cpu(s->fifo[SVGA_FIFO_STOP]); ++ ++ /* Check range and alignment. */ ++ if ((s->fifo_min | s->fifo_max | s->fifo_next | s->fifo_stop) & 3) { ++ return 0; ++ } ++ if (s->fifo_min < sizeof(uint32_t) * 4) { ++ return 0; ++ } ++ if (s->fifo_max > SVGA_FIFO_SIZE || ++ s->fifo_min >= SVGA_FIFO_SIZE || ++ s->fifo_stop >= SVGA_FIFO_SIZE || ++ s->fifo_next >= SVGA_FIFO_SIZE) { ++ return 0; ++ } ++ if (s->fifo_max < s->fifo_min + 10 * 1024) { ++ return 0; ++ } ++ ++ num = s->fifo_next - s->fifo_stop; + if (num < 0) +- num += CMD(max) - CMD(min); ++ num += s->fifo_max - s->fifo_min; + return num >> 2; + } + + static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s) + { +- uint32_t cmd = s->fifo[CMD(stop) >> 2]; +- s->cmd->stop = cpu_to_le32(CMD(stop) + 4); +- if (CMD(stop) >= CMD(max)) +- s->cmd->stop = s->cmd->min; ++ uint32_t cmd = s->fifo[s->fifo_stop >> 2]; ++ ++ s->fifo_stop += 4; ++ if (s->fifo_stop >= s->fifo_max) { ++ s->fifo_stop = s->fifo_min; ++ } ++ s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop); + return cmd; + } + +@@ -580,7 +598,7 @@ + len = vmsvga_fifo_length(s); + while (len > 0) { + /* May need to go back to the start of the command if incomplete */ +- cmd_start = s->cmd->stop; ++ cmd_start = s->fifo_stop; + + switch (cmd = vmsvga_fifo_read(s)) { + case SVGA_CMD_UPDATE: +@@ -726,7 +744,8 @@ + break; + + rewind: +- s->cmd->stop = cmd_start; ++ s->fifo_stop = cmd_start; ++ s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop); + break; + } + } +@@ -916,16 +935,6 @@ + case SVGA_REG_CONFIG_DONE: + if (value) { + s->fifo = (uint32_t *) s->fifo_ptr; +- /* Check range and alignment. */ +- if ((CMD(min) | CMD(max) | +- CMD(next_cmd) | CMD(stop)) & 3) +- break; +- if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) +- break; +- if (CMD(max) > SVGA_FIFO_SIZE) +- break; +- if (CMD(max) < CMD(min) + 10 * 1024) +- break; + } + s->config = !!value; + break; only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/CVE-2016-4453.patch +++ qemu-kvm-1.0+noroms/debian/patches/CVE-2016-4453.patch @@ -0,0 +1,44 @@ +Backport of: + +From 4e68a0ee17dad7b8d870df0081d4ab2e079016c2 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 30 May 2016 09:09:21 +0200 +Subject: [PATCH] vmsvga: don't process more than 1024 fifo commands at once +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +vmsvga_fifo_run is called in regular intervals (on each display update) +and will resume where it left off. So we can simply exit the loop, +without having to worry about how processing will continue. + +Fixes: CVE-2016-4453 +Cc: qemu-stable@nongnu.org +Cc: P J P +Reported-by: 李强 +Signed-off-by: Gerd Hoffmann +Message-id: 1464592161-18348-5-git-send-email-kraxel@redhat.com +--- + hw/display/vmware_vga.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +Index: qemu-kvm-1.0+noroms/hw/vmware_vga.c +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/vmware_vga.c 2016-08-04 07:40:07.414082081 -0400 ++++ qemu-kvm-1.0+noroms/hw/vmware_vga.c 2016-08-04 07:40:07.410082048 -0400 +@@ -590,13 +590,13 @@ + static void vmsvga_fifo_run(struct vmsvga_state_s *s) + { + uint32_t cmd, colour; +- int args, len; ++ int args, len, maxloop = 1024; + int x, y, dx, dy, width, height; + struct vmsvga_cursor_definition_s cursor; + uint32_t cmd_start; + + len = vmsvga_fifo_length(s); +- while (len > 0) { ++ while (len > 0 && --maxloop > 0) { + /* May need to go back to the start of the command if incomplete */ + cmd_start = s->fifo_stop; +