dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame 0001-vnc-fix-memory-corruption-CVE-2015-5225.patch

821139
From: Gerd Hoffmann <kraxel@redhat.com>
821139
Date: Mon, 17 Aug 2015 19:56:53 +0200
821139
Subject: [PATCH] vnc: fix memory corruption (CVE-2015-5225)
821139
MIME-Version: 1.0
821139
Content-Type: text/plain; charset=UTF-8
821139
Content-Transfer-Encoding: 8bit
821139
821139
The _cmp_bytes variable added by commit "bea60dd ui/vnc: fix potential
821139
memory corruption issues" can become negative.  Result is (possibly
821139
exploitable) memory corruption.  Reason for that is it uses the stride
821139
instead of bytes per scanline to apply limits.
821139
821139
For the server surface is is actually fine.  vnc creates that itself,
821139
there is never any padding and thus scanline length always equals stride.
821139
821139
For the guest surface scanline length and stride are typically identical
821139
too, but it doesn't has to be that way.  So add and use a new variable
821139
(guest_ll) for the guest scanline length.  Also rename min_stride to
821139
line_bytes to make more clear what it actually is.  Finally sprinkle
821139
in an assert() to make sure we never use a negative _cmp_bytes again.
821139
821139
Reported-by: 范祚至(库特) <zuozhi.fzz@alibaba-inc.com>
821139
Reviewed-by: P J P <ppandit@redhat.com>
821139
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
821139
(cherry picked from commit eb8934b0418b3b1d125edddc4fc334a54334a49b)
821139
---
821139
 ui/vnc.c | 15 ++++++++++-----
821139
 1 file changed, 10 insertions(+), 5 deletions(-)
821139
821139
diff --git a/ui/vnc.c b/ui/vnc.c
821139
index e26973a..caf82f5 100644
821139
--- a/ui/vnc.c
821139
+++ b/ui/vnc.c
821139
@@ -2872,7 +2872,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
821139
                     pixman_image_get_width(vd->server));
821139
     int height = MIN(pixman_image_get_height(vd->guest.fb),
821139
                      pixman_image_get_height(vd->server));
821139
-    int cmp_bytes, server_stride, min_stride, guest_stride, y = 0;
821139
+    int cmp_bytes, server_stride, line_bytes, guest_ll, guest_stride, y = 0;
821139
     uint8_t *guest_row0 = NULL, *server_row0;
821139
     VncState *vs;
821139
     int has_dirty = 0;
821139
@@ -2891,17 +2891,21 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
821139
      * Update server dirty map.
821139
      */
821139
     server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
821139
-    server_stride = guest_stride = pixman_image_get_stride(vd->server);
821139
+    server_stride = guest_stride = guest_ll =
821139
+        pixman_image_get_stride(vd->server);
821139
     cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES,
821139
                     server_stride);
821139
     if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
821139
         int width = pixman_image_get_width(vd->server);
821139
         tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
821139
     } else {
821139
+        int guest_bpp =
821139
+            PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb));
821139
         guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
821139
         guest_stride = pixman_image_get_stride(vd->guest.fb);
821139
+        guest_ll = pixman_image_get_width(vd->guest.fb) * ((guest_bpp + 7) / 8);
821139
     }
821139
-    min_stride = MIN(server_stride, guest_stride);
821139
+    line_bytes = MIN(server_stride, guest_ll);
821139
 
821139
     for (;;) {
821139
         int x;
821139
@@ -2932,9 +2936,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
821139
             if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
821139
                 continue;
821139
             }
821139
-            if ((x + 1) * cmp_bytes > min_stride) {
821139
-                _cmp_bytes = min_stride - x * cmp_bytes;
821139
+            if ((x + 1) * cmp_bytes > line_bytes) {
821139
+                _cmp_bytes = line_bytes - x * cmp_bytes;
821139
             }
821139
+            assert(_cmp_bytes >= 0);
821139
             if (memcmp(server_ptr, guest_ptr, _cmp_bytes) == 0) {
821139
                 continue;
821139
             }