QEMU is a FAST! processor emulator
CentOS Sources
2017-04-18 976a86fff9adb9a2a6968b9f73fe9a615266f59b
import qemu-kvm-1.5.3-126.el7_3.6
7 files added
1 files modified
1664 ■■■■■ changed files
SOURCES/kvm-cirrus-add-option-to-disable-blitter.patch 84 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-fix-cirrus_invalidate_region.patch 51 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch 49 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch 630 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch 455 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch 297 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch 64 ●●●●● patch | view | raw | blame | history
SPECS/qemu-kvm.spec 34 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-cirrus-add-option-to-disable-blitter.patch
New file
@@ -0,0 +1,84 @@
From 319f3876fafc35412bbf0ef6797c6764c95af6f3 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:03 +0100
Subject: [PATCH 3/7] cirrus: add option to disable blitter
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-4-git-send-email-kraxel@redhat.com>
Patchwork-id: 74424
O-Subject: [RHEL-7.4 qemu-kvm PATCH 3/7] cirrus: add option to disable blitter
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
Ok, we have this beast in the cirrus code which is not used at all by
modern guests, except when you try to find security holes in qemu.  So,
add an option to disable blitter altogether.  Guests released within
the last ten years should not show any rendering issues if you turn off
blitter support.
There are no known bugs in the cirrus blitter code.  But in the past we
hoped a few times already that we've finally nailed the last issue.  So
having some easy way to mitigate in case yet another blitter issue shows
up certainly makes me sleep a bit better at night.
For completeness:  The by far better way to mitigate is to switch away
from cirrus and use stdvga instead.  Or something more modern like
virtio-vga in case your guest has support for it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1489494540-15745-1-git-send-email-kraxel@redhat.com
(cherry picked from commit 827bd5172641f2a360ff9a3bad57bcf82e7f03f0)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/display/cirrus_vga.c
---
 hw/display/cirrus_vga.c | 9 +++++++++
 1 file changed, 9 insertions(+)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 83cef70..86b4c8b 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -203,6 +203,7 @@ typedef struct CirrusVGAState {
     uint8_t cirrus_hidden_palette[48];
     uint32_t hw_cursor_x;
     uint32_t hw_cursor_y;
+    bool enable_blitter;
     int cirrus_blt_pixelwidth;
     int cirrus_blt_width;
     int cirrus_blt_height;
@@ -954,6 +955,10 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
 {
     uint8_t blt_rop;
+    if (!s->enable_blitter) {
+        goto bitblt_ignore;
+    }
+
     s->vga.gr[0x31] |= CIRRUS_BLT_BUSY;
     s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1;
@@ -2995,6 +3000,8 @@ static int vga_initfn(ISADevice *dev)
 static Property isa_cirrus_vga_properties[] = {
     DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState,
                        cirrus_vga.vga.vram_size_mb, 16),
+    DEFINE_PROP_BOOL("blitter", struct ISACirrusVGAState,
+                       cirrus_vga.enable_blitter, true),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -3060,6 +3067,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
 static Property pci_vga_cirrus_properties[] = {
     DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
                        cirrus_vga.vga.vram_size_mb, 16),
+    DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState,
+                     cirrus_vga.enable_blitter, true),
     DEFINE_PROP_END_OF_LIST(),
 };
--
1.8.3.1
SOURCES/kvm-cirrus-fix-cirrus_invalidate_region.patch
New file
@@ -0,0 +1,51 @@
From 6c17f6355cac0bc40bae876acf4d31e32978991f Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:04 +0100
Subject: [PATCH 4/7] cirrus: fix cirrus_invalidate_region
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-5-git-send-email-kraxel@redhat.com>
Patchwork-id: 74423
O-Subject: [RHEL-7.4 qemu-kvm PATCH 4/7] cirrus: fix cirrus_invalidate_region
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
off_cur_end is exclusive, so off_cur_end == cirrus_addr_mask is valid.
Fix calculation to make sure to allow that, otherwise the assert added
by commit f153b563f8cf121aebf5a2fff5f0110faf58ccb3 can trigger for valid
blits.
Test case: boot windows nt 4.0
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1489579606-26020-1-git-send-email-kraxel@redhat.com
(cherry picked from commit e048dac616748273c2153490e9fdf1da242f0cad)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 86b4c8b..aab6e02 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -661,11 +661,11 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
     }
     for (y = 0; y < lines; y++) {
-    off_cur = off_begin;
-    off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
+        off_cur = off_begin;
+        off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1;
         assert(off_cur_end >= off_cur);
         memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
-    off_begin += off_pitch;
+        off_begin += off_pitch;
     }
 }
--
1.8.3.1
SOURCES/kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
New file
@@ -0,0 +1,49 @@
From 8c2a803f9ba8b4293c207917a2acfcfac0548d24 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:07 +0100
Subject: [PATCH 7/7] cirrus: fix off-by-one in
 cirrus_bitblt_rop_bkwd_transp_*_16
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-8-git-send-email-kraxel@redhat.com>
Patchwork-id: 74422
O-Subject: [RHEL-7.4 qemu-kvm PATCH 7/7] cirrus: fix off-by-one in cirrus_bitblt_rop_bkwd_transp_*_16
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
The switch from pointers to addresses (commit
026aeffcb4752054830ba203020ed6eb05bcaba8 and
ffaf857778286ca54e3804432a2369a279e73aa7) added
a off-by-one bug to 16bit backward blits.  Fix.
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 1489735296-19047-1-git-send-email-kraxel@redhat.com
(cherry picked from commit f019722cbbb45aea153294fc8921fcc96a4d3fa2)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga_rop.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 16dffb8..c1fc070 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -220,7 +220,7 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
-            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
+            ROP_OP_TR_16(s, dstaddr - 1, cirrus_src16(s, srcaddr - 1), transp);
             dstaddr -= 2;
             srcaddr -= 2;
         }
--
1.8.3.1
SOURCES/kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch
New file
@@ -0,0 +1,630 @@
From c4928f394f862c78024f4dccb6ea1398dc743c49 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:05 +0100
Subject: [PATCH 5/7] cirrus: stop passing around dst pointers in the blitter
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-6-git-send-email-kraxel@redhat.com>
Patchwork-id: 74421
O-Subject: [RHEL-7.4 qemu-kvm PATCH 5/7] cirrus: stop passing around dst pointers in the blitter
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
Instead pass around the address (aka offset into vga memory).  Calculate
the pointer in the rop_* functions, after applying the mask to the
address, to make sure the address stays within the valid range.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1489574872-8679-1-git-send-email-kraxel@redhat.com
(cherry picked from commit 026aeffcb4752054830ba203020ed6eb05bcaba8)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c      |  20 +++---
 hw/display/cirrus_vga_rop.h  | 161 +++++++++++++++++++++++++------------------
 hw/display/cirrus_vga_rop2.h |  97 +++++++++++++-------------
 3 files changed, 153 insertions(+), 125 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index aab6e02..003cc4c 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -174,11 +174,12 @@
 struct CirrusVGAState;
 typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
-                                     uint8_t * dst, const uint8_t * src,
+                                     uint32_t dstaddr, const uint8_t *src,
                      int dstpitch, int srcpitch,
                      int bltwidth, int bltheight);
 typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
-                              uint8_t *dst, int dst_pitch, int width, int height);
+                              uint32_t dstaddr, int dst_pitch,
+                              int width, int height);
 typedef struct CirrusVGAState {
     VGACommonState vga;
@@ -315,14 +316,14 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
 }
 static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
-                                  uint8_t *dst,const uint8_t *src,
+                                  uint32_t dstaddr, const uint8_t *src,
                                   int dstpitch,int srcpitch,
                                   int bltwidth,int bltheight)
 {
 }
 static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
-                                   uint8_t *dst,
+                                   uint32_t dstaddr,
                                    int dstpitch, int bltwidth,int bltheight)
 {
 }
@@ -672,11 +673,8 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
 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 (videosrc) {
         switch (s->vga.get_bpp(&s->vga)) {
         case 8:
@@ -705,7 +703,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
         return 0;
     }
-    (*s->cirrus_rop) (s, dst, src,
+    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src,
                       s->cirrus_blt_dstpitch, 0,
                       s->cirrus_blt_width, s->cirrus_blt_height);
     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
@@ -724,7 +722,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,
+    rop_func(s, s->cirrus_blt_dstaddr,
              s->cirrus_blt_dstpitch,
              s->cirrus_blt_width, s->cirrus_blt_height);
     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
@@ -791,7 +789,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
         }
     }
-    (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,
+    (*s->cirrus_rop) (s, 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);
@@ -842,7 +840,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_rop)(s, 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);
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index a4f96c6..3b16d70 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -22,31 +22,65 @@
  * THE SOFTWARE.
  */
-static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src)
+static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s,
+                                          uint32_t dstaddr, uint8_t src)
 {
+    uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
     *dst = ROP_FN(*dst, src);
 }
-static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src)
+static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s,
+                                             uint32_t dstaddr, uint8_t src,
+                                             uint8_t transp)
 {
+    uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
+    uint8_t pixel = ROP_FN(*dst, src);
+    if (pixel != transp) {
+        *dst = pixel;
+    }
+}
+
+static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s,
+                                           uint32_t dstaddr, uint16_t src)
+{
+    uint16_t *dst = (uint16_t *)
+        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
     *dst = ROP_FN(*dst, src);
 }
-static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src)
+static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s,
+                                              uint32_t dstaddr, uint16_t src,
+                                              uint16_t transp)
+{
+    uint16_t *dst = (uint16_t *)
+        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
+    uint16_t pixel = ROP_FN(*dst, src);
+    if (pixel != transp) {
+        *dst = pixel;
+    }
+}
+
+static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s,
+                                           uint32_t dstaddr, uint32_t src)
 {
+    uint32_t *dst = (uint32_t *)
+        (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]);
     *dst = ROP_FN(*dst, src);
 }
-#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s)
-#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s)
-#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s)
+#define ROP_OP(st, d, s)           glue(rop_8_, ROP_NAME)(st, d, s)
+#define ROP_OP_TR(st, d, s, t)     glue(rop_tr_8_, ROP_NAME)(st, d, s, t)
+#define ROP_OP_16(st, d, s)        glue(rop_16_, ROP_NAME)(st, d, s)
+#define ROP_OP_TR_16(st, d, s, t)  glue(rop_tr_16_, ROP_NAME)(st, d, s, t)
+#define ROP_OP_32(st, d, s)        glue(rop_32_, ROP_NAME)(st, d, s)
 #undef ROP_FN
 static void
 glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
-                             uint8_t *dst,const uint8_t *src,
-                             int dstpitch,int srcpitch,
-                             int bltwidth,int bltheight)
+                                       uint32_t dstaddr,
+                                       const uint8_t *src,
+                                       int dstpitch, int srcpitch,
+                                       int bltwidth, int bltheight)
 {
     int x,y;
     dstpitch -= bltwidth;
@@ -59,43 +93,47 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP(dst, *src);
-            dst++;
+            ROP_OP(s, dstaddr, *src);
+            dstaddr++;
             src++;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
 static void
 glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
-                                        uint8_t *dst,const uint8_t *src,
-                                        int dstpitch,int srcpitch,
-                                        int bltwidth,int bltheight)
+                                        uint32_t dstaddr,
+                                        const uint8_t *src,
+                                        int dstpitch, int srcpitch,
+                                        int bltwidth, int bltheight)
 {
     int x,y;
     dstpitch += bltwidth;
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP(dst, *src);
-            dst--;
+            ROP_OP(s, dstaddr, *src);
+            dstaddr--;
             src--;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
-                               uint8_t *dst,const uint8_t *src,
-                               int dstpitch,int srcpitch,
-                               int bltwidth,int bltheight)
+                                                       uint32_t dstaddr,
+                                                       const uint8_t *src,
+                                                       int dstpitch,
+                                                       int srcpitch,
+                                                       int bltwidth,
+                                                       int bltheight)
 {
     int x,y;
-    uint8_t p;
+    uint8_t transp = s->vga.gr[0x34];
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
@@ -105,48 +143,50 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-        p = *dst;
-            ROP_OP(&p, *src);
-        if (p != s->vga.gr[0x34]) *dst = p;
-            dst++;
+            ROP_OP_TR(s, dstaddr, *src, transp);
+            dstaddr++;
             src++;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
-                            uint8_t *dst,const uint8_t *src,
-                            int dstpitch,int srcpitch,
-                            int bltwidth,int bltheight)
+                                                        uint32_t dstaddr,
+                                                        const uint8_t *src,
+                                                        int dstpitch,
+                                                        int srcpitch,
+                                                        int bltwidth,
+                                                        int bltheight)
 {
     int x,y;
-    uint8_t p;
+    uint8_t transp = s->vga.gr[0x34];
     dstpitch += bltwidth;
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-        p = *dst;
-            ROP_OP(&p, *src);
-        if (p != s->vga.gr[0x34]) *dst = p;
-            dst--;
+            ROP_OP_TR(s, dstaddr, *src, transp);
+            dstaddr--;
             src--;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
-                            uint8_t *dst,const uint8_t *src,
-                            int dstpitch,int srcpitch,
-                            int bltwidth,int bltheight)
+                                                        uint32_t dstaddr,
+                                                        const uint8_t *src,
+                                                        int dstpitch,
+                                                        int srcpitch,
+                                                        int bltwidth,
+                                                        int bltheight)
 {
     int x,y;
-    uint8_t p1, p2;
+    uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
@@ -156,46 +196,35 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
-        p1 = *dst;
-        p2 = *(dst+1);
-            ROP_OP(&p1, *src);
-            ROP_OP(&p2, *(src + 1));
-        if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
-        *dst = p1;
-        *(dst+1) = p2;
-        }
-            dst+=2;
-            src+=2;
+            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
+            dstaddr += 2;
+            src += 2;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
-                             uint8_t *dst,const uint8_t *src,
-                             int dstpitch,int srcpitch,
-                             int bltwidth,int bltheight)
+                                                         uint32_t dstaddr,
+                                                         const uint8_t *src,
+                                                         int dstpitch,
+                                                         int srcpitch,
+                                                         int bltwidth,
+                                                         int bltheight)
 {
     int x,y;
-    uint8_t p1, p2;
+    uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
     dstpitch += bltwidth;
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
-        p1 = *(dst-1);
-        p2 = *dst;
-            ROP_OP(&p1, *(src - 1));
-            ROP_OP(&p2, *src);
-        if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
-        *(dst-1) = p1;
-        *dst = p2;
-        }
-            dst-=2;
-            src-=2;
+            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
+            dstaddr -= 2;
+            src -= 2;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
         src += srcpitch;
     }
 }
diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
index d28bcc6..bc92f0e 100644
--- a/hw/display/cirrus_vga_rop2.h
+++ b/hw/display/cirrus_vga_rop2.h
@@ -23,27 +23,29 @@
  */
 #if DEPTH == 8
-#define PUTPIXEL()    ROP_OP(&d[0], col)
+#define PUTPIXEL(s, a, c)    ROP_OP(s, a, c)
 #elif DEPTH == 16
-#define PUTPIXEL()    ROP_OP_16((uint16_t *)&d[0], col)
+#define PUTPIXEL(s, a, c)    ROP_OP_16(s, a, c)
 #elif DEPTH == 24
-#define PUTPIXEL()    ROP_OP(&d[0], col);        \
-                      ROP_OP(&d[1], (col >> 8)); \
-                      ROP_OP(&d[2], (col >> 16))
+#define PUTPIXEL(s, a, c)    do {          \
+        ROP_OP(s, a,     c);               \
+        ROP_OP(s, a + 1, (col >> 8));      \
+        ROP_OP(s, a + 2, (col >> 16));     \
+    } while (0)
 #elif DEPTH == 32
-#define PUTPIXEL()    ROP_OP_32(((uint32_t *)&d[0]), col)
+#define PUTPIXEL(s, a, c)    ROP_OP_32(s, a, c)
 #else
 #error unsupported DEPTH
 #endif
 static void
 glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
-     (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src,
+     (CirrusVGAState *s, uint32_t dstaddr,
+      const uint8_t *src,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
-    uint8_t *d;
+    uint32_t addr;
     int x, y, pattern_y, pattern_pitch, pattern_x;
     unsigned int col;
     const uint8_t *src1;
@@ -63,7 +65,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
     pattern_y = s->cirrus_blt_srcaddr & 7;
     for(y = 0; y < bltheight; y++) {
         pattern_x = skipleft;
-        d = dst + skipleft;
+        addr = dstaddr + skipleft;
         src1 = src + pattern_y * pattern_pitch;
         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
 #if DEPTH == 8
@@ -82,23 +84,23 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
             col = ((uint32_t *)(src1 + pattern_x))[0];
             pattern_x = (pattern_x + 4) & 31;
 #endif
-            PUTPIXEL();
-            d += (DEPTH / 8);
+            PUTPIXEL(s, addr, col);
+            addr += (DEPTH / 8);
         }
         pattern_y = (pattern_y + 1) & 7;
-        dst += dstpitch;
+        dstaddr += dstpitch;
     }
 }
 /* NOTE: srcpitch is ignored */
 static void
 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
-     (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src,
+     (CirrusVGAState *s, uint32_t dstaddr,
+      const uint8_t *src,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
-    uint8_t *d;
+    uint32_t addr;
     int x, y;
     unsigned bits, bits_xor;
     unsigned int col;
@@ -123,7 +125,7 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         bitmask = 0x80 >> srcskipleft;
         bits = *src++ ^ bits_xor;
-        d = dst + dstskipleft;
+        addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             if ((bitmask & 0xff) == 0) {
                 bitmask = 0x80;
@@ -131,24 +133,24 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
             }
             index = (bits & bitmask);
             if (index) {
-                PUTPIXEL();
+                PUTPIXEL(s, addr, col);
             }
-            d += (DEPTH / 8);
+            addr += (DEPTH / 8);
             bitmask >>= 1;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
     }
 }
 static void
 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
-     (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src,
+     (CirrusVGAState *s, uint32_t dstaddr,
+      const uint8_t *src,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
     uint32_t colors[2];
-    uint8_t *d;
+    uint32_t addr;
     int x, y;
     unsigned bits;
     unsigned int col;
@@ -161,29 +163,29 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         bitmask = 0x80 >> srcskipleft;
         bits = *src++;
-        d = dst + dstskipleft;
+        addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             if ((bitmask & 0xff) == 0) {
                 bitmask = 0x80;
                 bits = *src++;
             }
             col = colors[!!(bits & bitmask)];
-            PUTPIXEL();
-            d += (DEPTH / 8);
+            PUTPIXEL(s, addr, col);
+            addr += (DEPTH / 8);
             bitmask >>= 1;
         }
-        dst += dstpitch;
+        dstaddr += dstpitch;
     }
 }
 static void
 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
-     (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src,
+     (CirrusVGAState *s, uint32_t dstaddr,
+      const uint8_t *src,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
-    uint8_t *d;
+    uint32_t addr;
     int x, y, bitpos, pattern_y;
     unsigned int bits, bits_xor;
     unsigned int col;
@@ -207,28 +209,28 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         bits = src[pattern_y] ^ bits_xor;
         bitpos = 7 - srcskipleft;
-        d = dst + dstskipleft;
+        addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             if ((bits >> bitpos) & 1) {
-                PUTPIXEL();
+                PUTPIXEL(s, addr, col);
             }
-            d += (DEPTH / 8);
+            addr += (DEPTH / 8);
             bitpos = (bitpos - 1) & 7;
         }
         pattern_y = (pattern_y + 1) & 7;
-        dst += dstpitch;
+        dstaddr += dstpitch;
     }
 }
 static void
 glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
-     (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src,
+     (CirrusVGAState *s, uint32_t dstaddr,
+      const uint8_t *src,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
     uint32_t colors[2];
-    uint8_t *d;
+    uint32_t addr;
     int x, y, bitpos, pattern_y;
     unsigned int bits;
     unsigned int col;
@@ -242,38 +244,37 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         bits = src[pattern_y];
         bitpos = 7 - srcskipleft;
-        d = dst + dstskipleft;
+        addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             col = colors[(bits >> bitpos) & 1];
-            PUTPIXEL();
-            d += (DEPTH / 8);
+            PUTPIXEL(s, addr, col);
+            addr += (DEPTH / 8);
             bitpos = (bitpos - 1) & 7;
         }
         pattern_y = (pattern_y + 1) & 7;
-        dst += dstpitch;
+        dstaddr += dstpitch;
     }
 }
 static void
 glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s,
-      uint8_t *dst, int dst_pitch,
+      uint32_t dstaddr, int dst_pitch,
       int width, int height)
 {
-    uint8_t *d, *d1;
+    uint32_t addr;
     uint32_t col;
     int x, y;
     col = s->cirrus_blt_fgcol;
-    d1 = dst;
     for(y = 0; y < height; y++) {
-        d = d1;
+        addr = dstaddr;
         for(x = 0; x < width; x += (DEPTH / 8)) {
-            PUTPIXEL();
-            d += (DEPTH / 8);
+            PUTPIXEL(s, addr, col);
+            addr += (DEPTH / 8);
         }
-        d1 += dst_pitch;
+        dstaddr += dst_pitch;
     }
 }
--
1.8.3.1
SOURCES/kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
New file
@@ -0,0 +1,455 @@
From d29af2a00b6126d2c3af535d128beeb80216c197 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:06 +0100
Subject: [PATCH 6/7] cirrus: stop passing around src pointers in the blitter
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-7-git-send-email-kraxel@redhat.com>
Patchwork-id: 74417
O-Subject: [RHEL-7.4 qemu-kvm PATCH 6/7] cirrus: stop passing around src pointers in the blitter
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
Does basically the same as "cirrus: stop passing around dst pointers in
the blitter", just for the src pointer instead of the dst pointer.
For the src we have to care about cputovideo blits though and fetch the
data from s->cirrus_bltbuf instead of vga memory.  The cirrus_src*()
helper functions handle that.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1489584487-3489-1-git-send-email-kraxel@redhat.com
(cherry picked from commit ffaf857778286ca54e3804432a2369a279e73aa7)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga.c      | 61 +++++++++++++++++++++++++++++++++++---------
 hw/display/cirrus_vga_rop.h  | 48 +++++++++++++++++-----------------
 hw/display/cirrus_vga_rop2.h | 38 ++++++++++++++-------------
 3 files changed, 93 insertions(+), 54 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 003cc4c..c1324ab 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -174,7 +174,7 @@
 struct CirrusVGAState;
 typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
-                                     uint32_t dstaddr, const uint8_t *src,
+                                     uint32_t dstaddr, uint32_t srcaddr,
                      int dstpitch, int srcpitch,
                      int bltwidth, int bltheight);
 typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
@@ -316,7 +316,7 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
 }
 static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
-                                  uint32_t dstaddr, const uint8_t *src,
+                                  uint32_t dstaddr, uint32_t srcaddr,
                                   int dstpitch,int srcpitch,
                                   int bltwidth,int bltheight)
 {
@@ -328,6 +328,45 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
 {
 }
+static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr)
+{
+    if (s->cirrus_srccounter) {
+        /* cputovideo */
+        return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)];
+    } else {
+        /* videotovideo */
+        return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask];
+    }
+}
+
+static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr)
+{
+    uint16_t *src;
+
+    if (s->cirrus_srccounter) {
+        /* cputovideo */
+        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1];
+    } else {
+        /* videotovideo */
+        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1];
+    }
+    return *src;
+}
+
+static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr)
+{
+    uint32_t *src;
+
+    if (s->cirrus_srccounter) {
+        /* cputovideo */
+        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3];
+    } else {
+        /* videotovideo */
+        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3];
+    }
+    return *src;
+}
+
 #define ROP_NAME 0
 #define ROP_FN(d, s) 0
 #include "cirrus_vga_rop.h"
@@ -670,10 +709,10 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
     }
 }
-static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
+static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s)
 {
     uint32_t patternsize;
-    uint8_t *src;
+    bool videosrc = !s->cirrus_srccounter;
     if (videosrc) {
         switch (s->vga.get_bpp(&s->vga)) {
@@ -694,16 +733,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
         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)) {
         return 0;
     }
-    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src,
+    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
+                      videosrc ? s->cirrus_blt_srcaddr : 0,
                       s->cirrus_blt_dstpitch, 0,
                       s->cirrus_blt_width, s->cirrus_blt_height);
     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
@@ -740,7 +777,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, true);
+    return cirrus_bitblt_common_patterncopy(s);
 }
 static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
@@ -790,7 +827,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
     }
     (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
-                      s->vga.vram_ptr + s->cirrus_blt_srcaddr,
+                      s->cirrus_blt_srcaddr,
               s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
               s->cirrus_blt_width, s->cirrus_blt_height);
@@ -833,7 +870,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, false);
+            cirrus_bitblt_common_patterncopy(s);
         the_end:
             s->cirrus_srccounter = 0;
             cirrus_bitblt_reset(s);
@@ -841,7 +878,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
             /* at least one scan line */
             do {
                 (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
-                                  s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+                                 0, 0, 0, s->cirrus_blt_width, 1);
                 cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
                                          s->cirrus_blt_width, 1);
                 s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 3b16d70..16dffb8 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -78,7 +78,7 @@ static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s,
 static void
 glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
                                        uint32_t dstaddr,
-                                       const uint8_t *src,
+                                       uint32_t srcaddr,
                                        int dstpitch, int srcpitch,
                                        int bltwidth, int bltheight)
 {
@@ -93,19 +93,19 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP(s, dstaddr, *src);
+            ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
             dstaddr++;
-            src++;
+            srcaddr++;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
 static void
 glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
                                         uint32_t dstaddr,
-                                        const uint8_t *src,
+                                        uint32_t srcaddr,
                                         int dstpitch, int srcpitch,
                                         int bltwidth, int bltheight)
 {
@@ -114,19 +114,19 @@ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP(s, dstaddr, *src);
+            ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
             dstaddr--;
-            src--;
+            srcaddr--;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
                                                        uint32_t dstaddr,
-                                                       const uint8_t *src,
+                                                       uint32_t srcaddr,
                                                        int dstpitch,
                                                        int srcpitch,
                                                        int bltwidth,
@@ -143,19 +143,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP_TR(s, dstaddr, *src, transp);
+            ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
             dstaddr++;
-            src++;
+            srcaddr++;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
                                                         uint32_t dstaddr,
-                                                        const uint8_t *src,
+                                                        uint32_t srcaddr,
                                                         int dstpitch,
                                                         int srcpitch,
                                                         int bltwidth,
@@ -167,19 +167,19 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
-            ROP_OP_TR(s, dstaddr, *src, transp);
+            ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
             dstaddr--;
-            src--;
+            srcaddr--;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
                                                         uint32_t dstaddr,
-                                                        const uint8_t *src,
+                                                        uint32_t srcaddr,
                                                         int dstpitch,
                                                         int srcpitch,
                                                         int bltwidth,
@@ -196,19 +196,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
-            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
+            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
             dstaddr += 2;
-            src += 2;
+            srcaddr += 2;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
 static void
 glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
                                                          uint32_t dstaddr,
-                                                         const uint8_t *src,
+                                                         uint32_t srcaddr,
                                                          int dstpitch,
                                                          int srcpitch,
                                                          int bltwidth,
@@ -220,12 +220,12 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     srcpitch += bltwidth;
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
-            ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp);
+            ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
             dstaddr -= 2;
-            src -= 2;
+            srcaddr -= 2;
         }
         dstaddr += dstpitch;
-        src += srcpitch;
+        srcaddr += srcpitch;
     }
 }
diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
index bc92f0e..b86bcd6 100644
--- a/hw/display/cirrus_vga_rop2.h
+++ b/hw/display/cirrus_vga_rop2.h
@@ -41,14 +41,14 @@
 static void
 glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s, uint32_t dstaddr,
-      const uint8_t *src,
+      uint32_t srcaddr,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
     uint32_t addr;
     int x, y, pattern_y, pattern_pitch, pattern_x;
     unsigned int col;
-    const uint8_t *src1;
+    uint32_t src1addr;
 #if DEPTH == 24
     int skipleft = s->vga.gr[0x2f] & 0x1f;
 #else
@@ -66,22 +66,24 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         pattern_x = skipleft;
         addr = dstaddr + skipleft;
-        src1 = src + pattern_y * pattern_pitch;
+        src1addr = srcaddr + pattern_y * pattern_pitch;
         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
 #if DEPTH == 8
-            col = src1[pattern_x];
+            col = cirrus_src(s, src1addr + pattern_x);
             pattern_x = (pattern_x + 1) & 7;
 #elif DEPTH == 16
-            col = ((uint16_t *)(src1 + pattern_x))[0];
+            col = cirrus_src16(s, src1addr + pattern_x);
             pattern_x = (pattern_x + 2) & 15;
 #elif DEPTH == 24
             {
-                const uint8_t *src2 = src1 + pattern_x * 3;
-                col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
+                uint32_t src2addr = src1addr + pattern_x * 3;
+                col = cirrus_src(s, src2addr) |
+                    (cirrus_src(s, src2addr + 1) << 8) |
+                    (cirrus_src(s, src2addr + 2) << 16);
                 pattern_x = (pattern_x + 1) & 7;
             }
 #else
-            col = ((uint32_t *)(src1 + pattern_x))[0];
+            col = cirrus_src32(s, src1addr + pattern_x);
             pattern_x = (pattern_x + 4) & 31;
 #endif
             PUTPIXEL(s, addr, col);
@@ -96,7 +98,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
 static void
 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s, uint32_t dstaddr,
-      const uint8_t *src,
+      uint32_t srcaddr,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
@@ -124,12 +126,12 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
     for(y = 0; y < bltheight; y++) {
         bitmask = 0x80 >> srcskipleft;
-        bits = *src++ ^ bits_xor;
+        bits = cirrus_src(s, srcaddr++) ^ bits_xor;
         addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             if ((bitmask & 0xff) == 0) {
                 bitmask = 0x80;
-                bits = *src++ ^ bits_xor;
+                bits = cirrus_src(s, srcaddr++) ^ bits_xor;
             }
             index = (bits & bitmask);
             if (index) {
@@ -145,7 +147,7 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
 static void
 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s, uint32_t dstaddr,
-      const uint8_t *src,
+      uint32_t srcaddr,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
@@ -162,12 +164,12 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
     colors[1] = s->cirrus_blt_fgcol;
     for(y = 0; y < bltheight; y++) {
         bitmask = 0x80 >> srcskipleft;
-        bits = *src++;
+        bits = cirrus_src(s, srcaddr++);
         addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
             if ((bitmask & 0xff) == 0) {
                 bitmask = 0x80;
-                bits = *src++;
+                bits = cirrus_src(s, srcaddr++);
             }
             col = colors[!!(bits & bitmask)];
             PUTPIXEL(s, addr, col);
@@ -181,7 +183,7 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
 static void
 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s, uint32_t dstaddr,
-      const uint8_t *src,
+      uint32_t srcaddr,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
@@ -207,7 +209,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
     pattern_y = s->cirrus_blt_srcaddr & 7;
     for(y = 0; y < bltheight; y++) {
-        bits = src[pattern_y] ^ bits_xor;
+        bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
         bitpos = 7 - srcskipleft;
         addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
@@ -225,7 +227,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
 static void
 glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
      (CirrusVGAState *s, uint32_t dstaddr,
-      const uint8_t *src,
+      uint32_t srcaddr,
       int dstpitch, int srcpitch,
       int bltwidth, int bltheight)
 {
@@ -242,7 +244,7 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
     pattern_y = s->cirrus_blt_srcaddr & 7;
     for(y = 0; y < bltheight; y++) {
-        bits = src[pattern_y];
+        bits = cirrus_src(s, srcaddr + pattern_y);
         bitpos = 7 - srcskipleft;
         addr = dstaddr + dstskipleft;
         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
--
1.8.3.1
SOURCES/kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch
New file
@@ -0,0 +1,297 @@
From de457fc23e747a0c622e0fd23e49893c1f1da460 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:02 +0100
Subject: [PATCH 2/7] cirrus/vnc: zap bitblit support from console code.
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-3-git-send-email-kraxel@redhat.com>
Patchwork-id: 74418
O-Subject: [RHEL-7.4 qemu-kvm PATCH 2/7] cirrus/vnc: zap bitblit support from console code.
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
There is a special code path (dpy_gfx_copy) to allow graphic emulation
notify user interface code about bitblit operations carryed out by
guests.  It is supported by cirrus and vnc server.  The intended purpose
is to optimize display scrolls and just send over the scroll op instead
of a full display update.
This is rarely used these days though because modern guests simply don't
use the cirrus blitter any more.  Any linux guest using the cirrus drm
driver doesn't.  Any windows guest newer than winxp doesn't ship with a
cirrus driver any more and thus uses the cirrus as simple framebuffer.
So this code tends to bitrot and bugs can go unnoticed for a long time.
See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
which fixes a bug lingering in the code for almost a year, added by
commit "c7628bf vnc: only alloc server surface with clients connected".
Also the vnc server will throttle the frame rate in case it figures the
network can't keep up (send buffers are full).  This doesn't work with
dpy_gfx_copy, for any copy operation sent to the vnc client we have to
send all outstanding updates beforehand, otherwise the vnc client might
run the client side blit on outdated data and thereby corrupt the
display.  So this dpy_gfx_copy "optimization" might even make things
worse on slow network links.
Lets kill it once for all.
Oh, and one more reason: Turns out (after writing the patch) we have a
security bug in that code path ...
Fixes: CVE-2016-9603
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1489494419-14340-1-git-send-email-kraxel@redhat.com
(cherry picked from commit 50628d3479e4f9aa97e323506856e394fe7ad7a6)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    include/ui/console.h
    ui/vnc.c
---
 hw/display/cirrus_vga.c | 12 ++-----
 include/ui/console.h    |  7 ----
 ui/console.c            | 28 ---------------
 ui/vnc.c                | 96 -------------------------------------------------
 4 files changed, 3 insertions(+), 140 deletions(-)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 1b972db..83cef70 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -790,21 +790,15 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
         }
     }
-    /* we have to flush all pending changes so that the copy
-       is generated at the appropriate moment in time */
-    if (notify)
-        graphic_hw_update(s->vga.con);
-
     (*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);
     if (notify) {
-        qemu_console_copy(s->vga.con,
-              sx, sy, dx, dy,
-              s->cirrus_blt_width / depth,
-              s->cirrus_blt_height);
+        dpy_gfx_update(s->vga.con, dx, dy,
+                       s->cirrus_blt_width / depth,
+                       s->cirrus_blt_height);
     }
     /* we don't have to notify the display that this portion has
diff --git a/include/ui/console.h b/include/ui/console.h
index 4307b5f..7f5fa66 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -159,9 +159,6 @@ typedef struct DisplayChangeListenerOps {
                            int x, int y, int w, int h);
     void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
                            struct DisplaySurface *new_surface);
-    void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
-                         int src_x, int src_y,
-                         int dst_x, int dst_y, int w, int h);
     void (*dpy_text_cursor)(DisplayChangeListener *dcl,
                             int x, int y);
@@ -216,8 +213,6 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl);
 void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
 void dpy_gfx_replace_surface(QemuConsole *con,
                              DisplaySurface *surface);
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
-                  int dst_x, int dst_y, int w, int h);
 void dpy_text_cursor(QemuConsole *con, int x, int y);
 void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
 void dpy_text_resize(QemuConsole *con, int w, int h);
@@ -295,8 +290,6 @@ void text_consoles_set_display(DisplayState *ds);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
 void qemu_console_resize(QemuConsole *con, int width, int height);
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
-                       int dst_x, int dst_y, int w, int h);
 DisplaySurface *qemu_console_surface(QemuConsole *con);
 DisplayState *qemu_console_displaystate(QemuConsole *console);
diff --git a/ui/console.c b/ui/console.c
index d422083..fb08ec0 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1461,27 +1461,6 @@ void dpy_refresh(DisplayState *s)
     }
 }
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
-                  int dst_x, int dst_y, int w, int h)
-{
-    DisplayState *s = con->ds;
-    DisplayChangeListener *dcl;
-
-    if (!qemu_console_is_visible(con)) {
-        return;
-    }
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (con != (dcl->con ? dcl->con : active_console)) {
-            continue;
-        }
-        if (dcl->ops->dpy_gfx_copy) {
-            dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
-        } else { /* TODO */
-            dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
-        }
-    }
-}
-
 void dpy_text_cursor(QemuConsole *con, int x, int y)
 {
     DisplayState *s = con->ds;
@@ -1843,13 +1822,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
     dpy_gfx_replace_surface(s, surface);
 }
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
-                       int dst_x, int dst_y, int w, int h)
-{
-    assert(con->console_type == GRAPHIC_CONSOLE);
-    dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
-}
-
 DisplaySurface *qemu_console_surface(QemuConsole *console)
 {
     return console->surface;
diff --git a/ui/vnc.c b/ui/vnc.c
index a0e2d33..c7a7853 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -417,7 +417,6 @@ out_error:
 */
 static int vnc_update_client(VncState *vs, int has_dirty);
-static int vnc_update_client_sync(VncState *vs, int has_dirty);
 static void vnc_disconnect_start(VncState *vs);
 static void vnc_colordepth(VncState *vs);
@@ -721,93 +720,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
     return n;
 }
-static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
-{
-    /* send bitblit op to the vnc client */
-    vnc_lock_output(vs);
-    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
-    vnc_write_u8(vs, 0);
-    vnc_write_u16(vs, 1); /* number of rects */
-    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
-    vnc_write_u16(vs, src_x);
-    vnc_write_u16(vs, src_y);
-    vnc_unlock_output(vs);
-    vnc_flush(vs);
-}
-
-static void vnc_dpy_copy(DisplayChangeListener *dcl,
-                         int src_x, int src_y,
-                         int dst_x, int dst_y, int w, int h)
-{
-    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
-    VncState *vs, *vn;
-    uint8_t *src_row;
-    uint8_t *dst_row;
-    int i, x, y, pitch, inc, w_lim, s;
-    int cmp_bytes;
-
-    vnc_refresh_server_surface(vd);
-    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
-        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-            vs->force_update = 1;
-            vnc_update_client_sync(vs, 1);
-            /* vs might be free()ed here */
-        }
-    }
-
-    /* do bitblit op on the local surface too */
-    pitch = vnc_server_fb_stride(vd);
-    src_row = vnc_server_fb_ptr(vd, src_x, src_y);
-    dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
-    y = dst_y;
-    inc = 1;
-    if (dst_y > src_y) {
-        /* copy backwards */
-        src_row += pitch * (h-1);
-        dst_row += pitch * (h-1);
-        pitch = -pitch;
-        y = dst_y + h - 1;
-        inc = -1;
-    }
-    w_lim = w - (16 - (dst_x % 16));
-    if (w_lim < 0)
-        w_lim = w;
-    else
-        w_lim = w - (w_lim % 16);
-    for (i = 0; i < h; i++) {
-        for (x = 0; x <= w_lim;
-                x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
-            if (x == w_lim) {
-                if ((s = w - w_lim) == 0)
-                    break;
-            } else if (!x) {
-                s = (16 - (dst_x % 16));
-                s = MIN(s, w_lim);
-            } else {
-                s = 16;
-            }
-            cmp_bytes = s * VNC_SERVER_FB_BYTES;
-            if (memcmp(src_row, dst_row, cmp_bytes) == 0)
-                continue;
-            memmove(dst_row, src_row, cmp_bytes);
-            QTAILQ_FOREACH(vs, &vd->clients, next) {
-                if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-                    set_bit(((x + dst_x) / 16), vs->dirty[y]);
-                }
-            }
-        }
-        src_row += pitch - w * VNC_SERVER_FB_BYTES;
-        dst_row += pitch - w * VNC_SERVER_FB_BYTES;
-        y += inc;
-    }
-
-    QTAILQ_FOREACH(vs, &vd->clients, next) {
-        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
-        }
-    }
-}
-
 static void vnc_mouse_set(DisplayChangeListener *dcl,
                           int x, int y, int visible)
 {
@@ -873,13 +785,6 @@ static int find_and_clear_dirty_height(struct VncState *vs,
     return h;
 }
-static int vnc_update_client_sync(VncState *vs, int has_dirty)
-{
-    int ret = vnc_update_client(vs, has_dirty);
-    vnc_jobs_join(vs);
-    return ret;
-}
-
 static int vnc_update_client(VncState *vs, int has_dirty)
 {
     if (vs->need_update && vs->csock != -1) {
@@ -2912,7 +2817,6 @@ static void vnc_listen_websocket_read(void *opaque)
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "vnc",
     .dpy_refresh       = vnc_refresh,
-    .dpy_gfx_copy      = vnc_dpy_copy,
     .dpy_gfx_update    = vnc_dpy_update,
     .dpy_gfx_switch    = vnc_dpy_switch,
     .dpy_mouse_set     = vnc_mouse_set,
--
1.8.3.1
SOURCES/kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch
New file
@@ -0,0 +1,64 @@
From d27fae125c1efd59ba3263260d41f8e054b070a2 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 21 Mar 2017 09:58:01 +0100
Subject: [PATCH 1/7] fix :cirrus_vga fix OOB read case qemu Segmentation fault
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1490090287-1503-2-git-send-email-kraxel@redhat.com>
Patchwork-id: 74419
O-Subject: [RHEL-7.4 qemu-kvm PATCH 1/7] fix :cirrus_vga fix OOB read case qemu Segmentation fault
Bugzilla: 1430059
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: hangaohuai <hangaohuai@huawei.com>
check the validity of parameters in cirrus_bitblt_rop_fwd_transp_xxx
and cirrus_bitblt_rop_fwd_xxx to avoid the OOB read which causes qemu Segmentation fault.
After the fix, we will touch the assert in
cirrus_invalidate_region:
assert(off_cur_end >= off_cur);
Signed-off-by: fangying <fangying1@huawei.com>
Signed-off-by: hangaohuai <hangaohuai@huawei.com>
Message-id: 20170314063919.16200-1-hangaohuai@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 215902d7b6fb50c6fc216fc74f770858278ed904)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/display/cirrus_vga_rop.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 9c7bb09..a4f96c6 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -98,6 +98,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     uint8_t p;
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
+
+    if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+        return;
+    }
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
         p = *dst;
@@ -144,6 +149,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     uint8_t p1, p2;
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
+
+    if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
+        return;
+    }
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
         p1 = *dst;
--
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}.5
Release: 126%{?dist}.6
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 10
License: GPLv2+ and LGPLv2+ and BSD
@@ -3432,6 +3432,20 @@
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
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1689: kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1690: kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1691: kvm-cirrus-add-option-to-disable-blitter.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1692: kvm-cirrus-fix-cirrus_invalidate_region.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1693: kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1694: kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1695: kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
BuildRequires: zlib-devel
@@ -5300,6 +5314,13 @@
%patch1686 -p1
%patch1687 -p1
%patch1688 -p1
%patch1689 -p1
%patch1690 -p1
%patch1691 -p1
%patch1692 -p1
%patch1693 -p1
%patch1694 -p1
%patch1695 -p1
%build
buildarch="%{kvm_target}-softmmu"
@@ -5745,6 +5766,17 @@
%{_mandir}/man8/qemu-nbd.8*
%changelog
* Fri Mar 24 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.6
- kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch [bz#1430059]
- kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch [bz#1430059]
- kvm-cirrus-add-option-to-disable-blitter.patch [bz#1430059]
- kvm-cirrus-fix-cirrus_invalidate_region.patch [bz#1430059]
- kvm-cirrus-stop-passing-around-dst-pointers-in-the-blitt.patch [bz#1430059]
- kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch [bz#1430059]
- kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch [bz#1430059]
- Resolves: bz#1430059
  (CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z])
* 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]