QEMU is a FAST! processor emulator
CentOS Sources
2017-03-02 4f5da8cf40ea809191d5b389aa6a63327196fdcf
import qemu-kvm-1.5.3-126.el7_3.5
20 files added
1 files modified
1718 ■■■■■ changed files
SOURCES/kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch 115 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-balloon-fix-segfault-and-harden-the-stats-queue.patch 138 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput.patch 70 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-allow-zero-source-pitch-in-pattern-fill-rops.patch 115 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-fix-blit-address-mask-handling.patch 115 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-fix-oob-access-issue-CVE-2017-2615.patch 61 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-fix-patterncopy-checks.patch 113 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-handle-negative-pitch-in-cirrus_invalidate_re.patch 64 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus_vga-fix-off-by-one-in-blit_region_is_unsafe.patch 59 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-display-cirrus-check-vga-bits-per-pixel-bpp-value.patch 89 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-display-cirrus-ignore-source-pitch-value-as-needed-i.patch 85 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-net-check-packet-payload-length.patch 64 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-add-virtqueue_rewind.patch 86 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-balloon-discard-virtqueue-element-on-reset.patch 54 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-balloon-fix-stats-vq-migration.patch 75 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-blk-Release-s-rq-queue-at-system_reset.patch 68 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-decrement-vq-inuse-in-virtqueue_discard.patch 48 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-introduce-virtqueue_discard.patch 66 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-introduce-virtqueue_unmap_sg.patch 70 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-virtio-zero-vq-inuse-in-virtio_reset.patch 63 ●●●●● patch | view | raw | blame | history
SPECS/qemu-kvm.spec 100 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch
New file
@@ -0,0 +1,115 @@
From 1cd1297bf694c0a91d75a87b4fd22c2b80807b49 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 10 Feb 2017 08:30:14 +0100
Subject: [PATCH 2/3] Revert "cirrus: allow zero source pitch in pattern fill
 rops"
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486715415-3462-3-git-send-email-kraxel@redhat.com>
Patchwork-id: 73774
O-Subject: [virt-devel] [RHEL-7.4 qemu-kvm PATCH 2/3] Revert "cirrus: allow zero source pitch in pattern fill rops"
Bugzilla: 1420490
CVE: CVE-2017-2620/20170221
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
This reverts commit 5858dd1801883309bdd208d72ddb81c4e9fee30c.
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/display/cirrus_vga.c
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Upstream: WIP (https://patchwork.ozlabs.org/patch/726074/)
---
 hw/display/cirrus_vga.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index fff9bf0..9a9501f 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -267,6 +267,9 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
 static bool blit_region_is_unsafe(struct CirrusVGAState *s,
                                   int32_t pitch, int32_t addr)
 {
+    if (!pitch) {
+        return true;
+    }
     if (pitch < 0) {
         int64_t min = addr
             + ((int64_t)s->cirrus_blt_height - 1) * pitch
@@ -285,11 +288,8 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
     return false;
 }
-static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
-                           bool zero_src_pitch_ok)
+static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
 {
-    int32_t check_pitch;
-
     /* should be the case, see cirrus_bitblt_start */
     assert(s->cirrus_blt_width > 0);
     assert(s->cirrus_blt_height > 0);
@@ -298,10 +298,6 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
         return true;
     }
-    if (!s->cirrus_blt_dstpitch) {
-        return true;
-    }
-
     if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
                               s->cirrus_blt_dstaddr)) {
         return true;
@@ -309,13 +305,7 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
     if (dst_only) {
         return false;
     }
-
-    check_pitch = s->cirrus_blt_srcpitch;
-    if (!zero_src_pitch_ok && !check_pitch) {
-        check_pitch = s->cirrus_blt_width;
-    }
-
-    if (blit_region_is_unsafe(s, check_pitch,
+    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
                               s->cirrus_blt_srcaddr)) {
         return true;
     }
@@ -710,7 +700,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
         src = s->cirrus_bltbuf;
     }
-    if (blit_is_unsafe(s, true, true)) {
+    if (blit_is_unsafe(s, true)) {
         return 0;
     }
@@ -729,7 +719,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 {
     cirrus_fill_t rop_func;
-    if (blit_is_unsafe(s, true, true)) {
+    if (blit_is_unsafe(s, true)) {
         return 0;
     }
     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
@@ -829,7 +819,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
 {
-    if (blit_is_unsafe(s, false, false))
+    if (blit_is_unsafe(s, false))
         return 0;
     return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
--
1.8.3.1
SOURCES/kvm-balloon-fix-segfault-and-harden-the-stats-queue.patch
New file
@@ -0,0 +1,138 @@
From 75255574498fad12727529c4ecbd4ccdabe86839 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:26 +0200
Subject: [PATCH 4/8] balloon: fix segfault and harden the stats queue
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-5-git-send-email-lprosek@redhat.com>
Patchwork-id: 72483
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 4/6] balloon: fix segfault and harden the stats queue
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
The segfault here is triggered by the driver notifying the stats queue
twice after adding a buffer to it. This effectively resets stats_vq_elem
back to NULL and QEMU crashes on the next stats timer tick in
balloon_stats_poll_cb.
This is a regression introduced in 51b19ebe4320f3dc, although admittedly
the device assumed too much about the stats queue protocol even before
that commit. This commit adds a few more checks and ensures that the one
stats buffer gets deallocated on device reset.
Cc: qemu-stable@nongnu.org
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 4eae2a657d1ff5ada56eb9b4966eae0eff333b0b)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
  * 1.5.3 does not return pointers from virtqueue_pop so only the
    "harden the stats queue" part of the upstream patch description
    applies
  * a new field stats_vq_elem_pending is introduced to keep track
    of the state of stats_vq_elem in lieu of its nullness upstream
  * virtio_balloon_device_reset only resets stats_vq_elem_pending
    because there is nothing to free
---
 hw/virtio/virtio-balloon.c         | 27 +++++++++++++++++++++++----
 include/hw/virtio/virtio-balloon.h |  1 +
 2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 016dc60..17b3029 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -95,13 +95,14 @@ static void balloon_stats_poll_cb(void *opaque)
     VirtIOBalloon *s = opaque;
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
-    if (!balloon_stats_supported(s)) {
+    if (!s->stats_vq_elem_pending || !balloon_stats_supported(s)) {
         /* re-schedule */
         balloon_stats_change_timer(s, s->stats_poll_interval);
         return;
     }
     virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset);
+    s->stats_vq_elem_pending = false;
     virtio_notify(vdev, s->svq);
 }
@@ -220,14 +221,22 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
-    VirtQueueElement *elem = &s->stats_vq_elem;
+    VirtQueueElement elem;
     VirtIOBalloonStat stat;
     size_t offset = 0;
     qemu_timeval tv;
-    if (!virtqueue_pop(vq, elem)) {
+    if (!virtqueue_pop(vq, &elem)) {
         goto out;
     }
+    if (s->stats_vq_elem_pending) {
+        /* This should never happen if the driver follows the spec. */
+        virtqueue_push(vq, &s->stats_vq_elem, 0);
+        virtio_notify(vdev, vq);
+    }
+
+    s->stats_vq_elem = elem;
+    s->stats_vq_elem_pending = true;
     /* Initialize the stats to get rid of any stale values.  This is only
      * needed to handle the case where a guest supports fewer stats than it
@@ -235,7 +244,7 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
      */
     reset_stats(s);
-    while (iov_to_buf(elem->out_sg, elem->out_num, offset, &stat, sizeof(stat))
+    while (iov_to_buf(elem.out_sg, elem.out_num, offset, &stat, sizeof(stat))
            == sizeof(stat)) {
         uint16_t tag = tswap16(stat.tag);
         uint64_t val = tswap64(stat.val);
@@ -384,6 +393,15 @@ static void virtio_balloon_device_exit(VirtIODevice *vdev)
     virtio_cleanup(vdev);
 }
+static void virtio_balloon_device_reset(VirtIODevice *vdev)
+{
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+
+    if (s->stats_vq_elem_pending) {
+        s->stats_vq_elem_pending = false;
+    }
+}
+
 static Property virtio_balloon_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -396,6 +414,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     vdc->init = virtio_balloon_device_init;
     vdc->exit = virtio_balloon_device_exit;
+    vdc->reset = virtio_balloon_device_reset;
     vdc->get_config = virtio_balloon_get_config;
     vdc->set_config = virtio_balloon_set_config;
     vdc->get_features = virtio_balloon_get_features;
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index f863bfe..a84736b 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -63,6 +63,7 @@ typedef struct VirtIOBalloon {
     uint32_t actual;
     uint64_t stats[VIRTIO_BALLOON_S_NR];
     VirtQueueElement stats_vq_elem;
+    bool stats_vq_elem_pending;
     size_t stats_vq_offset;
     QEMUTimer *stats_timer;
     int64_t stats_last_update;
--
1.8.3.1
SOURCES/kvm-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput.patch
New file
@@ -0,0 +1,70 @@
From e894ec03d7e6229488ae24d83809009162a0f9e0 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 10 Feb 2017 08:30:15 +0100
Subject: [PATCH 3/3] cirrus: add blit_is_unsafe call to
 cirrus_bitblt_cputovideo
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486715415-3462-4-git-send-email-kraxel@redhat.com>
Patchwork-id: 73773
O-Subject: [virt-devel] [EMBARGOED RHEL-7.4 qemu-kvm PATCH 3/3] cirrus: add blit_is_unsafe call to cirrus_bitblt_cputovideo
Bugzilla: 1420490
CVE: CVE-2017-2620/20170221
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
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.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Upstream: TBD (embargoed until Feb 21st)
Signed-off-by: Miroslav Rezanina <mrezanin@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 9a9501f..1b972db 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -894,6 +894,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
 {
     int w;
+    if (blit_is_unsafe(s, true)) {
+        return 0;
+    }
+
     s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
     s->cirrus_srcptr = &s->cirrus_bltbuf[0];
     s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
@@ -919,6 +923,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
SOURCES/kvm-cirrus-allow-zero-source-pitch-in-pattern-fill-rops.patch
New file
@@ -0,0 +1,115 @@
From 9fd5f5b599e19c4485c3c7e6689081965e833df6 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:50 +0100
Subject: [PATCH 6/8] cirrus: allow zero source pitch in pattern fill rops
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-6-git-send-email-kraxel@redhat.com>
Patchwork-id: 73569
O-Subject: [RHEL-7.4 qemu-kvm PATCH 5/7] cirrus: allow zero source pitch in pattern fill rops
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
The rops used by cirrus_bitblt_common_patterncopy only use
the destination pitch, so the source pitch shoul allowed to
be zero and the blit with used for the range check around the
source address.
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Message-id: 1485272138-23249-1-git-send-email-w.bumiller@proxmox.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 5858dd1801883309bdd208d72ddb81c4e9fee30c)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index e09076a..b040ab1 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -267,9 +267,6 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
 static bool blit_region_is_unsafe(struct CirrusVGAState *s,
                                   int32_t pitch, int32_t addr)
 {
-    if (!pitch) {
-        return true;
-    }
     if (pitch < 0) {
         int64_t min = addr
             + ((int64_t)s->cirrus_blt_height-1) * pitch;
@@ -289,8 +286,11 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
     return false;
 }
-static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
+static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
+                           bool zero_src_pitch_ok)
 {
+    int32_t check_pitch;
+
     /* should be the case, see cirrus_bitblt_start */
     assert(s->cirrus_blt_width > 0);
     assert(s->cirrus_blt_height > 0);
@@ -299,6 +299,10 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
         return true;
     }
+    if (!s->cirrus_blt_dstpitch) {
+        return true;
+    }
+
     if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
                               s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
         return true;
@@ -306,7 +310,13 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
     if (dst_only) {
         return false;
     }
-    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
+
+    check_pitch = s->cirrus_blt_srcpitch;
+    if (!zero_src_pitch_ok && !check_pitch) {
+        check_pitch = s->cirrus_blt_width;
+    }
+
+    if (blit_region_is_unsafe(s, check_pitch,
                               s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
         return true;
     }
@@ -676,8 +686,9 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
     dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
-    if (blit_is_unsafe(s, false))
+    if (blit_is_unsafe(s, false, true)) {
         return 0;
+    }
     (*s->cirrus_rop) (s, dst, src,
                       s->cirrus_blt_dstpitch, 0,
@@ -694,7 +705,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 {
     cirrus_fill_t rop_func;
-    if (blit_is_unsafe(s, true)) {
+    if (blit_is_unsafe(s, true, true)) {
         return 0;
     }
     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
@@ -798,7 +809,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
 {
-    if (blit_is_unsafe(s, false))
+    if (blit_is_unsafe(s, false, false))
         return 0;
     return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
--
1.8.3.1
SOURCES/kvm-cirrus-fix-blit-address-mask-handling.patch
New file
@@ -0,0 +1,115 @@
From fdb1ec384fe65b7ca2ab7303b56c2731e5999058 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:51 +0100
Subject: [PATCH 7/8] cirrus: fix blit address mask handling
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-7-git-send-email-kraxel@redhat.com>
Patchwork-id: 73570
O-Subject: [RHEL-7.4 qemu-kvm PATCH 6/7] cirrus: fix blit address mask handling
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
Apply the cirrus_addr_mask to cirrus_blt_dstaddr and cirrus_blt_srcaddr
right after assigning them, in cirrus_bitblt_start(), instead of having
this all over the place in the cirrus code, and missing a few places.
Reported-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1485338996-17095-1-git-send-email-kraxel@redhat.com
(cherry picked from commit 60cd23e85151525ab26591394c4e7e06fa07d216)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index b040ab1..6aa29a3 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -304,7 +304,7 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
     }
     if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
-                              s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
+                              s->cirrus_blt_dstaddr)) {
         return true;
     }
     if (dst_only) {
@@ -317,7 +317,7 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
     }
     if (blit_region_is_unsafe(s, check_pitch,
-                              s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
+                              s->cirrus_blt_srcaddr)) {
         return true;
     }
@@ -684,7 +684,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
 {
     uint8_t *dst;
-    dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
+    dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr;
     if (blit_is_unsafe(s, false, true)) {
         return 0;
@@ -709,7 +709,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
         return 0;
     }
     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
-    rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+    rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
              s->cirrus_blt_dstpitch,
              s->cirrus_blt_width, s->cirrus_blt_height);
     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
@@ -727,9 +727,8 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
 {
-    return cirrus_bitblt_common_patterncopy(s,
-                        s->vga.vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
-                                            s->cirrus_addr_mask));
+    return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr +
+                                            (s->cirrus_blt_srcaddr & ~7));
 }
 static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
@@ -783,10 +782,8 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
     if (notify)
         graphic_hw_update(s->vga.con);
-    (*s->cirrus_rop) (s, s->vga.vram_ptr +
-              (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
-              s->vga.vram_ptr +
-              (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+    (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
+                      s->vga.vram_ptr + s->cirrus_blt_srcaddr,
               s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
               s->cirrus_blt_width, s->cirrus_blt_height);
@@ -837,8 +834,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
         } else {
             /* at least one scan line */
             do {
-                (*s->cirrus_rop)(s, s->vga.vram_ptr +
-                                 (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+                (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
                                   s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
                 cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
                                          s->cirrus_blt_width, 1);
@@ -957,6 +953,9 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
     s->cirrus_blt_modeext = s->vga.gr[0x33];
     blt_rop = s->vga.gr[0x32];
+    s->cirrus_blt_dstaddr &= s->cirrus_addr_mask;
+    s->cirrus_blt_srcaddr &= s->cirrus_addr_mask;
+
 #ifdef DEBUG_BITBLT
     printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
            blt_rop,
--
1.8.3.1
SOURCES/kvm-cirrus-fix-oob-access-issue-CVE-2017-2615.patch
New file
@@ -0,0 +1,61 @@
From 55c542cca671a5a130c44359c73d1e908353418e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:52 +0100
Subject: [PATCH 8/8] cirrus: fix oob access issue (CVE-2017-2615)
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-8-git-send-email-kraxel@redhat.com>
Patchwork-id: 73565
O-Subject: [RHEL-7.4 qemu-kvm PATCH 7/7] cirrus: fix oob access issue (CVE-2017-2615)
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Li Qiang <liqiang6-s@360.cn>
When doing bitblt copy in backward mode, we should minus the
blt width first just like the adding in the forward mode. This
can avoid the oob access of the front of vga's vram.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
{ kraxel: with backward blits (negative pitch) addr is the topmost
          address, so check it as-is against vram size ]
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Fixes: d3532a0db02296e687711b8cdc7791924efccea0 (CVE-2014-8106)
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1485938101-26602-1-git-send-email-kraxel@redhat.com
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 62d4c6bd5263bb8413a06c80144fc678df6dfb64)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 6aa29a3..e0e39ef 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -269,10 +269,9 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
 {
     if (pitch < 0) {
         int64_t min = addr
-            + ((int64_t)s->cirrus_blt_height-1) * pitch;
-        int32_t max = addr
-            + s->cirrus_blt_width;
-        if (min < 0 || max > s->vga.vram_size) {
+            + ((int64_t)s->cirrus_blt_height - 1) * pitch
+            - s->cirrus_blt_width;
+        if (min < -1 || addr >= s->vga.vram_size) {
             return true;
         }
     } else {
--
1.8.3.1
SOURCES/kvm-cirrus-fix-patterncopy-checks.patch
New file
@@ -0,0 +1,113 @@
From 46da39c9f9a9a72cf9e833d46ce10d785581ce63 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 10 Feb 2017 08:30:13 +0100
Subject: [PATCH 1/3] cirrus: fix patterncopy checks
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486715415-3462-2-git-send-email-kraxel@redhat.com>
Patchwork-id: 73775
O-Subject: [virt-devel] [RHEL-7.4 qemu-kvm PATCH 1/3] cirrus: fix patterncopy checks
Bugzilla: 1420490
CVE: CVE-2017-2620/20170221
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
The blit_region_is_unsafe checks don't work correctly for the
patterncopy source.  It's a fixed-sized region, which doesn't
depend on cirrus_blt_{width,height}.  So go do the check in
cirrus_bitblt_common_patterncopy instead, then tell blit_is_unsafe that
it doesn't need to verify the source.  Also handle the case where we
blit from cirrus_bitbuf correctly.
This patch replaces 5858dd1801883309bdd208d72ddb81c4e9fee30c.
Security impact:  I think for the most part error on the safe side this
time, refusing blits which should have been allowed.
Only exception is placing the blit source at the end of the video ram,
so cirrus_blt_srcaddr + 256 goes beyond the end of video memory.  But
even in that case I'm not fully sure this actually allows read access to
host memory.  To trick the commit 5858dd18 security checks one has to
pick very small cirrus_blt_{width,height} values, which in turn implies
only a fraction of the blit source will actually be used.
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Upstream: WIP (https://patchwork.ozlabs.org/patch/726080/)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index e0e39ef..fff9bf0 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -678,14 +678,39 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
     }
 }
-static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
-                        const uint8_t * src)
+static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
 {
+    uint32_t patternsize;
     uint8_t *dst;
+    uint8_t *src;
     dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr;
-    if (blit_is_unsafe(s, false, true)) {
+    if (videosrc) {
+        switch (s->vga.get_bpp(&s->vga)) {
+        case 8:
+            patternsize = 64;
+            break;
+        case 15:
+        case 16:
+            patternsize = 128;
+            break;
+        case 24:
+        case 32:
+        default:
+            patternsize = 256;
+            break;
+        }
+        s->cirrus_blt_srcaddr &= ~(patternsize - 1);
+        if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
+            return 0;
+        }
+        src = s->vga.vram_ptr + s->cirrus_blt_srcaddr;
+    } else {
+        src = s->cirrus_bltbuf;
+    }
+
+    if (blit_is_unsafe(s, true, true)) {
         return 0;
     }
@@ -726,8 +751,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
 {
-    return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr +
-                                            (s->cirrus_blt_srcaddr & ~7));
+    return cirrus_bitblt_common_patterncopy(s, true);
 }
 static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
@@ -826,7 +850,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
     if (s->cirrus_srccounter > 0) {
         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
-            cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
+            cirrus_bitblt_common_patterncopy(s, false);
         the_end:
             s->cirrus_srccounter = 0;
             cirrus_bitblt_reset(s);
--
1.8.3.1
SOURCES/kvm-cirrus-handle-negative-pitch-in-cirrus_invalidate_re.patch
New file
@@ -0,0 +1,64 @@
From 1d7bdd730d1537f931a95897b14fdb6c5754ea2c Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:49 +0100
Subject: [PATCH 5/8] cirrus: handle negative pitch in
 cirrus_invalidate_region()
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-5-git-send-email-kraxel@redhat.com>
Patchwork-id: 73566
O-Subject: [RHEL-7.4 qemu-kvm PATCH 4/7] cirrus: handle negative pitch in cirrus_invalidate_region()
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
cirrus_invalidate_region() calls memory_region_set_dirty()
on a per-line basis, always ranging from off_begin to
off_begin+bytesperline. With a negative pitch off_begin
marks the top most used address and thus we need to do an
initial shift backwards by a line for negative pitches of
backward blits, otherwise the first iteration covers the
line going from the start offset forwards instead of
backwards.
Additionally since the start address is inclusive, if we
shift by a full `bytesperline` we move to the first address
*not* included in the blit, so we only shift by one less
than bytesperline.
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Message-id: 1485352137-29367-1-git-send-email-w.bumiller@proxmox.com
[ kraxel: codestyle fixes ]
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit f153b563f8cf121aebf5a2fff5f0110faf58ccb3)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 5 +++++
 1 file changed, 5 insertions(+)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index c8f2f26..e09076a 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -656,9 +656,14 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
     int off_cur;
     int off_cur_end;
+    if (off_pitch < 0) {
+        off_begin -= bytesperline - 1;
+    }
+
     for (y = 0; y < lines; y++) {
     off_cur = off_begin;
     off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
+        assert(off_cur_end >= off_cur);
         memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
     off_begin += off_pitch;
     }
--
1.8.3.1
SOURCES/kvm-cirrus_vga-fix-off-by-one-in-blit_region_is_unsafe.patch
New file
@@ -0,0 +1,59 @@
From 900ccf5cf6497234e1d3b1e80f4dfa8a60bcfb06 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:46 +0100
Subject: [PATCH 2/8] cirrus_vga: fix off-by-one in blit_region_is_unsafe
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-2-git-send-email-kraxel@redhat.com>
Patchwork-id: 73564
O-Subject: [RHEL-7.4 qemu-kvm PATCH 1/7] cirrus_vga: fix off-by-one in blit_region_is_unsafe
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
The "max" value is being compared with >=, but addr + width points to
the first byte that will _not_ be copied.  Laszlo suggested using a
"greater than" comparison, instead of subtracting one like it is
already done above for the height, so that max remains always positive.
The mistake is "safe"---it will reject some blits, but will never cause
out-of-bounds writes.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 1455121059-18280-1-git-send-email-pbonzini@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit d2ba7ecb348d3b996fcd920cf1ca7b72722c1dfd)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 717ecdb..c42dfcf 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -272,14 +272,14 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
             + ((int64_t)s->cirrus_blt_height-1) * pitch;
         int32_t max = addr
             + s->cirrus_blt_width;
-        if (min < 0 || max >= s->vga.vram_size) {
+        if (min < 0 || max > s->vga.vram_size) {
             return true;
         }
     } else {
         int64_t max = addr
             + ((int64_t)s->cirrus_blt_height-1) * pitch
             + s->cirrus_blt_width;
-        if (max >= s->vga.vram_size) {
+        if (max > s->vga.vram_size) {
             return true;
         }
     }
--
1.8.3.1
SOURCES/kvm-display-cirrus-check-vga-bits-per-pixel-bpp-value.patch
New file
@@ -0,0 +1,89 @@
From e0ec8bdaf64a147c83334ae6f59e279c4560d01b Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:47 +0100
Subject: [PATCH 3/8] display: cirrus: check vga bits per pixel(bpp) value
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-3-git-send-email-kraxel@redhat.com>
Patchwork-id: 73568
O-Subject: [RHEL-7.4 qemu-kvm PATCH 2/7] display: cirrus: check vga bits per pixel(bpp) value
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Prasad J Pandit <pjp@fedoraproject.org>
In Cirrus CLGD 54xx VGA Emulator, if cirrus graphics mode is VGA,
'cirrus_get_bpp' returns zero(0), which could lead to a divide
by zero error in while copying pixel data. The same could occur
via blit pitch values. Add check to avoid it.
Reported-by: Huawei PSIRT <psirt@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 1476776717-24807-1-git-send-email-ppandit@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 4299b90e9ba9ce5ca9024572804ba751aa1a7e70)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index c42dfcf..dacfac6 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -267,6 +267,9 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
 static bool blit_region_is_unsafe(struct CirrusVGAState *s,
                                   int32_t pitch, int32_t addr)
 {
+    if (!pitch) {
+        return true;
+    }
     if (pitch < 0) {
         int64_t min = addr
             + ((int64_t)s->cirrus_blt_height-1) * pitch;
@@ -710,7 +713,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
                                             s->cirrus_addr_mask));
 }
-static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 {
     int sx = 0, sy = 0;
     int dx = 0, dy = 0;
@@ -724,6 +727,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
         int width, height;
         depth = s->vga.get_bpp(&s->vga) / 8;
+        if (!depth) {
+            return 0;
+        }
         s->vga.get_resolution(&s->vga, &width, &height);
         /* extra x, y */
@@ -778,6 +784,8 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
                 s->cirrus_blt_height);
+
+    return 1;
 }
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
@@ -785,11 +793,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
     if (blit_is_unsafe(s))
         return 0;
-    cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
+    return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
             s->cirrus_blt_srcaddr - s->vga.start_addr,
             s->cirrus_blt_width, s->cirrus_blt_height);
-
-    return 1;
 }
 /***************************************
--
1.8.3.1
SOURCES/kvm-display-cirrus-ignore-source-pitch-value-as-needed-i.patch
New file
@@ -0,0 +1,85 @@
From 3178cae91f9fc3ddd025f1daa415b74ed387b6ca Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 7 Feb 2017 10:07:48 +0100
Subject: [PATCH 4/8] display: cirrus: ignore source pitch value as needed in
 blit_is_unsafe
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1486462072-32174-4-git-send-email-kraxel@redhat.com>
Patchwork-id: 73563
O-Subject: [RHEL-7.4 qemu-kvm PATCH 3/7] display: cirrus: ignore source pitch value as needed in blit_is_unsafe
Bugzilla: 1418232
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Bruce Rogers <brogers@suse.com>
Commit 4299b90 added a check which is too broad, given that the source
pitch value is not required to be initialized for solid fill operations.
This patch refines the blit_is_unsafe() check to ignore source pitch in
that case. After applying the above commit as a security patch, we
noticed the SLES 11 SP4 guest gui failed to initialize properly.
Signed-off-by: Bruce Rogers <brogers@suse.com>
Message-id: 20170109203520.5619-1-brogers@suse.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 913a87885f589d263e682c2eb6637c6e14538061)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index dacfac6..c8f2f26 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -289,7 +289,7 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
     return false;
 }
-static bool blit_is_unsafe(struct CirrusVGAState *s)
+static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
 {
     /* should be the case, see cirrus_bitblt_start */
     assert(s->cirrus_blt_width > 0);
@@ -303,6 +303,9 @@ static bool blit_is_unsafe(struct CirrusVGAState *s)
                               s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
         return true;
     }
+    if (dst_only) {
+        return false;
+    }
     if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
                               s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
         return true;
@@ -668,7 +671,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
     dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
-    if (blit_is_unsafe(s))
+    if (blit_is_unsafe(s, false))
         return 0;
     (*s->cirrus_rop) (s, dst, src,
@@ -686,7 +689,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 {
     cirrus_fill_t rop_func;
-    if (blit_is_unsafe(s)) {
+    if (blit_is_unsafe(s, true)) {
         return 0;
     }
     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
@@ -790,7 +793,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
 {
-    if (blit_is_unsafe(s))
+    if (blit_is_unsafe(s, false))
         return 0;
     return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
--
1.8.3.1
SOURCES/kvm-net-check-packet-payload-length.patch
New file
@@ -0,0 +1,64 @@
From 6d126da8f958c57413a4505d98cb4a3ff48cbbfe Mon Sep 17 00:00:00 2001
From: "wexu@redhat.com" <wexu@redhat.com>
Date: Wed, 21 Dec 2016 06:04:24 +0100
Subject: [PATCH] net: check packet payload length
RH-Author: wexu@redhat.com
Message-id: <1482300264-29708-2-git-send-email-wexu@redhat.com>
Patchwork-id: 73088
O-Subject: [RHEL-7.4/7.3.z qemu-kvm Patch v2] net: check packet payload length
Bugzilla: 1398217
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Prasad J Pandit <pjp@fedoraproject.org>
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.
This patch is to fix CVE-2016-2857.
https://access.redhat.com/security/cve/CVE-2016-2857
Reported-by: Liu Ling <liuling-it@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit 362786f14a753d8a5256ef97d7c10ed576d6572b)
Signed-off-by: Wei Xu <wexu@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 net/checksum.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/net/checksum.c b/net/checksum.c
index 14c0855..0942437 100644
--- a/net/checksum.c
+++ b/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;
--
1.8.3.1
SOURCES/kvm-virtio-add-virtqueue_rewind.patch
New file
@@ -0,0 +1,86 @@
From f7d6a76475d29e0edb5456e62492117b87f4bc41 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Thu, 10 Nov 2016 23:00:50 +0100
Subject: [PATCH 7/8] virtio: add virtqueue_rewind()
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1478797251-10302-1-git-send-email-lprosek@redhat.com>
Patchwork-id: 72818
O-Subject: [PATCH v2 7/6] virtio: add virtqueue_rewind()
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
virtqueue_discard() requires a VirtQueueElement but virtio-balloon does
not migrate its in-use element.  Introduce a new function that is
similar to virtqueue_discard() but doesn't require a VirtQueueElement.
This will allow virtio-balloon to access element again after migration
with the usual proviso that the guest may have modified the vring since
last time.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Roman Kagan <rkagan@virtuozzo.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 297a75e6c55d91db2704a3d6e4029d99c7df51fd)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/virtio/virtio.c         | 22 ++++++++++++++++++++++
 include/hw/virtio/virtio.h |  1 +
 2 files changed, 23 insertions(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index cdb21b1..fe6b032 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -259,6 +259,28 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
     virtqueue_unmap_sg(vq, elem, len);
 }
+/* virtqueue_rewind:
+ * @vq: The #VirtQueue
+ * @num: Number of elements to push back
+ *
+ * Pretend that elements weren't popped from the virtqueue.  The next
+ * virtqueue_pop() will refetch the oldest element.
+ *
+ * Use virtqueue_discard() instead if you have a VirtQueueElement.
+ *
+ * Returns: true on success, false if @num is greater than the number of in use
+ * elements.
+ */
+bool virtqueue_rewind(VirtQueue *vq, unsigned int num)
+{
+    if (num > vq->inuse) {
+        return false;
+    }
+    vq->last_avail_idx -= num;
+    vq->inuse -= num;
+    return true;
+}
+
 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 de32425..d9bfe4c 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -167,6 +167,7 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
 void virtqueue_flush(VirtQueue *vq, unsigned int count);
 void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
                        unsigned int len);
+bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
 void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                     unsigned int len, unsigned int idx);
--
1.8.3.1
SOURCES/kvm-virtio-balloon-discard-virtqueue-element-on-reset.patch
New file
@@ -0,0 +1,54 @@
From a1c91f04449eea0e678aeef78914213f092b7a19 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:27 +0200
Subject: [PATCH 5/8] virtio-balloon: discard virtqueue element on reset
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-6-git-send-email-lprosek@redhat.com>
Patchwork-id: 72484
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 5/6] virtio-balloon: discard virtqueue element on reset
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
The one pending element is being freed but not discarded on device
reset, which causes svq->inuse to creep up, eventually hitting the
"Virtqueue size exceeded" error.
Properly discarding the element on device reset makes sure that its
buffers are unmapped and the inuse counter stays balanced.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Roman Kagan <rkagan@virtuozzo.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 104e70cae78bd4afd95d948c6aff188f10508a9c)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
  * s->stats_vq_elem => &s->stats_vq_elem because the field is not
    s pointer in 1.5.3
---
 hw/virtio/virtio-balloon.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 17b3029..faf93f7 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -398,6 +398,7 @@ static void virtio_balloon_device_reset(VirtIODevice *vdev)
     VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     if (s->stats_vq_elem_pending) {
+        virtqueue_discard(s->svq, &s->stats_vq_elem, 0);
         s->stats_vq_elem_pending = false;
     }
 }
--
1.8.3.1
SOURCES/kvm-virtio-balloon-fix-stats-vq-migration.patch
New file
@@ -0,0 +1,75 @@
From 6d5c0e0e98907244d72e7828337d7ff6160b6b80 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Thu, 10 Nov 2016 23:00:51 +0100
Subject: [PATCH 8/8] virtio-balloon: fix stats vq migration
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1478797251-10302-2-git-send-email-lprosek@redhat.com>
Patchwork-id: 72819
O-Subject: [PATCH v2 8/6] virtio-balloon: fix stats vq migration
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
The statistics virtqueue is not migrated properly because virtio-balloon
does not include s->stats_vq_elem in the migration stream.
After migration the statistics virtqueue hangs because the host never
completes the last element (s->stats_vq_elem is NULL on the destination
QEMU).  Therefore the guest never submits new elements and the virtqueue
is hung.
Instead of changing the migration stream format in an incompatible way,
detect the migration case and rewind the virtqueue so the last element
can be completed.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Roman Kagan <rkagan@virtuozzo.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Suggested-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 4a1e48becab81020adfb74b22c76a595f2d02a01)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/virtio/virtio-balloon.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index faf93f7..1a60d3c 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -403,6 +403,18 @@ static void virtio_balloon_device_reset(VirtIODevice *vdev)
     }
 }
+static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status)
+{
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+
+    if (!s->stats_vq_elem_pending && vdev->vm_running &&
+        (status & VIRTIO_CONFIG_S_DRIVER_OK) && virtqueue_rewind(s->svq, 1)) {
+        /* poll stats queue for the element we have discarded when the VM
+         * was stopped */
+        virtio_balloon_receive_stats(vdev, s->svq);
+    }
+}
+
 static Property virtio_balloon_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -419,6 +431,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     vdc->get_config = virtio_balloon_get_config;
     vdc->set_config = virtio_balloon_set_config;
     vdc->get_features = virtio_balloon_get_features;
+    vdc->set_status = virtio_balloon_set_status;
 }
 static const TypeInfo virtio_balloon_info = {
--
1.8.3.1
SOURCES/kvm-virtio-blk-Release-s-rq-queue-at-system_reset.patch
New file
@@ -0,0 +1,68 @@
From cc9a8ce29ba364abcf019f6fe44b218255b9e4d7 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Wed, 8 Feb 2017 07:05:34 +0100
Subject: [PATCH 1/8] virtio-blk: Release s->rq queue at system_reset
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170208070534.10571-1-famz@redhat.com>
Patchwork-id: 73642
O-Subject: [RHEL-7.3.z qemu-kvm PATCH] virtio-blk: Release s->rq queue at system_reset
Bugzilla: 1420049
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
At system_reset, there is no point in retrying the queued request,
because the driver that issued the request won't be around any more.
Analyzed-by: Laszlo Ersek <lersek@redhat.com>
Reported-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 1470278654-13525-2-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 26307f6aa451708b8c60a49d605a78bbd29f70ef)
 Conflicts:
    hw/block/virtio-blk.c
The context is different. The hunk is placed below bdrv_drain_all() with
the comment updated to match downstream.
There is no virtio_blk_free_request in qemu-kvm in RHEL 7, use g_free().
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/block/virtio-blk.c | 8 ++++++++
 1 file changed, 8 insertions(+)
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 4f6aa22..462ac81 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -474,6 +474,7 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
 static void virtio_blk_reset(VirtIODevice *vdev)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
+    VirtIOBlockReq *req;
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
     if (s->dataplane) {
@@ -487,6 +488,13 @@ static void virtio_blk_reset(VirtIODevice *vdev)
      */
     bdrv_drain_all();
     bdrv_set_enable_write_cache(s->bs, s->original_wce);
+    /* We drop queued requests after bdrv_drain_all() because bdrv_drain_all()
+     * itself can produce them. */
+    while (s->rq) {
+        req = s->rq;
+        s->rq = req->next;
+        g_free(req);
+    }
 }
 /* coalesce internal state, copy to pci i/o region 0
--
1.8.3.1
SOURCES/kvm-virtio-decrement-vq-inuse-in-virtqueue_discard.patch
New file
@@ -0,0 +1,48 @@
From c24e1c927bad95d84e0ffab665baff98d91fb916 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:25 +0200
Subject: [PATCH 3/8] virtio: decrement vq->inuse in virtqueue_discard()
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-4-git-send-email-lprosek@redhat.com>
Patchwork-id: 72482
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 3/6] virtio: decrement vq->inuse in virtqueue_discard()
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
virtqueue_discard() moves vq->last_avail_idx back so the element can be
popped again.  It's necessary to decrement vq->inuse to avoid "leaking"
the element count.
Cc: qemu-stable@nongnu.org
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 58a83c61496eeb0d31571a07a51bc1947e3379ac)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/virtio/virtio.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 91c9642..87a7639 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -255,6 +255,7 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
                        unsigned int len)
 {
     vq->last_avail_idx--;
+    vq->inuse--;
     virtqueue_unmap_sg(vq, elem, len);
 }
--
1.8.3.1
SOURCES/kvm-virtio-introduce-virtqueue_discard.patch
New file
@@ -0,0 +1,66 @@
From b5c6f7a910c5c16ac34ef2436d0a56991e0166e3 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:24 +0200
Subject: [PATCH 2/8] virtio: introduce virtqueue_discard()
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-3-git-send-email-lprosek@redhat.com>
Patchwork-id: 72481
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 2/6] virtio: introduce virtqueue_discard()
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Jason Wang <jasowang@redhat.com>
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@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 29b9f5efd78ae0f9cc02dd169b6e80d2c404bade)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@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 5ee899a..91c9642 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -251,6 +251,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 9e22865..de32425 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -165,6 +165,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);
--
1.8.3.1
SOURCES/kvm-virtio-introduce-virtqueue_unmap_sg.patch
New file
@@ -0,0 +1,70 @@
From fc6f666f00182fe587068bd45e4e9e6d135d03fb Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:23 +0200
Subject: [PATCH 1/8] virtio: introduce virtqueue_unmap_sg()
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-2-git-send-email-lprosek@redhat.com>
Patchwork-id: 72480
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 1/6] virtio: introduce virtqueue_unmap_sg()
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Factor out sg unmapping logic. This will be reused by the patch that
can discard descriptor.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Andrew James <andrew.james@hpe.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit ce317461573bac12b10d67699b4ddf1f97cf066c)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@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 0df4ed3..5ee899a 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -228,14 +228,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);
@@ -251,6 +249,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;
--
1.8.3.1
SOURCES/kvm-virtio-zero-vq-inuse-in-virtio_reset.patch
New file
@@ -0,0 +1,63 @@
From e3e5226d8ed3907bb818eb8db74175c08c011459 Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Wed, 5 Oct 2016 17:22:28 +0200
Subject: [PATCH 6/8] virtio: zero vq->inuse in virtio_reset()
RH-Author: Ladi Prosek <lprosek@redhat.com>
Message-id: <1475666548-9186-7-git-send-email-lprosek@redhat.com>
Patchwork-id: 72485
O-Subject: [RHEL-7.4 qemu-kvm v2 PATCH 6/6] virtio: zero vq->inuse in virtio_reset()
Bugzilla: 1393484
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
vq->inuse must be zeroed upon device reset like most other virtqueue
fields.
In theory, virtio_reset() just needs assert(vq->inuse == 0) since
devices must clean up in-flight requests during reset (requests cannot
not be leaked!).
In practice, it is difficult to achieve vq->inuse == 0 across reset
because balloon, blk, 9p, etc implement various different strategies for
cleaning up requests.  Most devices call g_free(elem) directly without
telling virtio.c that the VirtQueueElement is cleaned up.  Therefore
vq->inuse is not decremented during reset.
This patch zeroes vq->inuse and trusts that devices are not leaking
VirtQueueElements across reset.
I will send a follow-up series that refactors request life-cycle across
all devices and converts vq->inuse = 0 into assert(vq->inuse == 0) but
this more invasive approach is not appropriate for stable trees.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Ladi Prosek <lprosek@redhat.com>
(cherry picked from commit 4b7f91ed0270a371e1933efa21ba600b6da23ab9)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/virtio/virtio.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 87a7639..cdb21b1 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -585,6 +585,7 @@ void virtio_reset(void *opaque)
         vdev->vq[i].signalled_used = 0;
         vdev->vq[i].signalled_used_valid = false;
         vdev->vq[i].notification = true;
+        vdev->vq[i].inuse = 0;
     }
 }
--
1.8.3.1
SPECS/qemu-kvm.spec
@@ -76,7 +76,7 @@
Summary: QEMU is a FAST! processor emulator
Name: %{pkgname}%{?pkgsuffix}
Version: 1.5.3
Release: 126%{?dist}.1
Release: 126%{?dist}.5
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 10
License: GPLv2+ and LGPLv2+ and BSD
@@ -3392,6 +3392,46 @@
Patch1667: kvm-ide-fix-halted-IO-segfault-at-reset.patch
# For bz#1392027 - shutdown rhel 5.11 guest failed and stop at "system halted"
Patch1668: kvm-hw-i386-regenerate-checked-in-AML-payload-RHEL-only.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1669: kvm-virtio-introduce-virtqueue_unmap_sg.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1670: kvm-virtio-introduce-virtqueue_discard.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1671: kvm-virtio-decrement-vq-inuse-in-virtqueue_discard.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1672: kvm-balloon-fix-segfault-and-harden-the-stats-queue.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1673: kvm-virtio-balloon-discard-virtqueue-element-on-reset.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1674: kvm-virtio-zero-vq-inuse-in-virtio_reset.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1675: kvm-virtio-add-virtqueue_rewind.patch
# For bz#1393484 - [RHEL7.3] KVM guest shuts itself down after 128th reboot
Patch1676: kvm-virtio-balloon-fix-stats-vq-migration.patch
# For bz#1398217 - CVE-2016-2857 qemu-kvm: Qemu: net: out of bounds read in net_checksum_calculate() [rhel-7.3.z]
Patch1677: kvm-net-check-packet-payload-length.patch
# For bz#1420049 - system_reset should clear pending request for error (virtio-blk)
Patch1678: kvm-virtio-blk-Release-s-rq-queue-at-system_reset.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1679: kvm-cirrus_vga-fix-off-by-one-in-blit_region_is_unsafe.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1680: kvm-display-cirrus-check-vga-bits-per-pixel-bpp-value.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1681: kvm-display-cirrus-ignore-source-pitch-value-as-needed-i.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1682: kvm-cirrus-handle-negative-pitch-in-cirrus_invalidate_re.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1683: kvm-cirrus-allow-zero-source-pitch-in-pattern-fill-rops.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1684: kvm-cirrus-fix-blit-address-mask-handling.patch
# For bz#1418232 - CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z]
Patch1685: kvm-cirrus-fix-oob-access-issue-CVE-2017-2615.patch
# For bz#1420490 - EMBARGOED CVE-2017-2620 qemu-kvm: Qemu: display: cirrus: potential arbitrary code execution via cirrus_bitblt_cputovideo [rhel-7.3.z]
Patch1686: kvm-cirrus-fix-patterncopy-checks.patch
# For bz#1420490 - EMBARGOED CVE-2017-2620 qemu-kvm: Qemu: display: cirrus: potential arbitrary code execution via cirrus_bitblt_cputovideo [rhel-7.3.z]
Patch1687: kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch
# For bz#1420490 - EMBARGOED CVE-2017-2620 qemu-kvm: Qemu: display: cirrus: potential arbitrary code execution via cirrus_bitblt_cputovideo [rhel-7.3.z]
Patch1688: kvm-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput.patch
BuildRequires: zlib-devel
@@ -5240,6 +5280,26 @@
%patch1666 -p1
%patch1667 -p1
%patch1668 -p1
%patch1669 -p1
%patch1670 -p1
%patch1671 -p1
%patch1672 -p1
%patch1673 -p1
%patch1674 -p1
%patch1675 -p1
%patch1676 -p1
%patch1677 -p1
%patch1678 -p1
%patch1679 -p1
%patch1680 -p1
%patch1681 -p1
%patch1682 -p1
%patch1683 -p1
%patch1684 -p1
%patch1685 -p1
%patch1686 -p1
%patch1687 -p1
%patch1688 -p1
%build
buildarch="%{kvm_target}-softmmu"
@@ -5685,6 +5745,44 @@
%{_mandir}/man8/qemu-nbd.8*
%changelog
* Mon Feb 13 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.5
- kvm-cirrus-fix-patterncopy-checks.patch [bz#1420490]
- kvm-Revert-cirrus-allow-zero-source-pitch-in-pattern-fil.patch [bz#1420490]
- kvm-cirrus-add-blit_is_unsafe-call-to-cirrus_bitblt_cput.patch [bz#1420490]
- Resolves: bz#1420490
  (EMBARGOED CVE-2017-2620 qemu-kvm: Qemu: display: cirrus: potential arbitrary code execution via cirrus_bitblt_cputovideo [rhel-7.3.z])
* Fri Feb 10 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.4
- kvm-virtio-blk-Release-s-rq-queue-at-system_reset.patch [bz#1420049]
- kvm-cirrus_vga-fix-off-by-one-in-blit_region_is_unsafe.patch [bz#1418232]
- kvm-display-cirrus-check-vga-bits-per-pixel-bpp-value.patch [bz#1418232]
- kvm-display-cirrus-ignore-source-pitch-value-as-needed-i.patch [bz#1418232]
- kvm-cirrus-handle-negative-pitch-in-cirrus_invalidate_re.patch [bz#1418232]
- kvm-cirrus-allow-zero-source-pitch-in-pattern-fill-rops.patch [bz#1418232]
- kvm-cirrus-fix-blit-address-mask-handling.patch [bz#1418232]
- kvm-cirrus-fix-oob-access-issue-CVE-2017-2615.patch [bz#1418232]
- Resolves: bz#1418232
  (CVE-2017-2615 qemu-kvm: Qemu: display: cirrus: oob access while doing bitblt copy backward mode [rhel-7.3.z])
- Resolves: bz#1420049
  (system_reset should clear pending request for error (virtio-blk))
* Wed Jan 04 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.3
- kvm-net-check-packet-payload-length.patch [bz#1398217]
- Resolves: bz#1398217
  (CVE-2016-2857 qemu-kvm: Qemu: net: out of bounds read in net_checksum_calculate() [rhel-7.3.z])
* Thu Nov 24 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.2
- kvm-virtio-introduce-virtqueue_unmap_sg.patch [bz#1393484]
- kvm-virtio-introduce-virtqueue_discard.patch [bz#1393484]
- kvm-virtio-decrement-vq-inuse-in-virtqueue_discard.patch [bz#1393484]
- kvm-balloon-fix-segfault-and-harden-the-stats-queue.patch [bz#1393484]
- kvm-virtio-balloon-discard-virtqueue-element-on-reset.patch [bz#1393484]
- kvm-virtio-zero-vq-inuse-in-virtio_reset.patch [bz#1393484]
- kvm-virtio-add-virtqueue_rewind.patch [bz#1393484]
- kvm-virtio-balloon-fix-stats-vq-migration.patch [bz#1393484]
- Resolves: bz#1393484
  ([RHEL7.3] KVM guest shuts itself down after 128th reboot)
* Fri Nov 11 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.1
- kvm-ide-fix-halted-IO-segfault-at-reset.patch [bz#1393042]
- kvm-hw-i386-regenerate-checked-in-AML-payload-RHEL-only.patch [bz#1392027]