|
|
619821 |
From e543257370cce5153bbcf0085a116e6aa4a6d91b Mon Sep 17 00:00:00 2001
|
|
|
619821 |
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
619821 |
Date: Wed, 22 Feb 2017 12:36:25 +0100
|
|
|
619821 |
Subject: [PATCH 07/24] vnc: fix memory corruption (CVE-2015-5225)
|
|
|
619821 |
MIME-Version: 1.0
|
|
|
619821 |
Content-Type: text/plain; charset=UTF-8
|
|
|
619821 |
Content-Transfer-Encoding: 8bit
|
|
|
619821 |
|
|
|
619821 |
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
619821 |
Message-id: <1487766986-6329-8-git-send-email-kraxel@redhat.com>
|
|
|
619821 |
Patchwork-id: 73978
|
|
|
619821 |
O-Subject: [RHEL-7.4 qemu-kvm PATCH 7/8] vnc: fix memory corruption (CVE-2015-5225)
|
|
|
619821 |
Bugzilla: 1377977
|
|
|
619821 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
619821 |
RH-Acked-by: Marc-André Lureau <mlureau@redhat.com>
|
|
|
619821 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
619821 |
|
|
|
619821 |
The _cmp_bytes variable added by commit "bea60dd ui/vnc: fix potential
|
|
|
619821 |
memory corruption issues" can become negative. Result is (possibly
|
|
|
619821 |
exploitable) memory corruption. Reason for that is it uses the stride
|
|
|
619821 |
instead of bytes per scanline to apply limits.
|
|
|
619821 |
|
|
|
619821 |
For the server surface is is actually fine. vnc creates that itself,
|
|
|
619821 |
there is never any padding and thus scanline length always equals stride.
|
|
|
619821 |
|
|
|
619821 |
For the guest surface scanline length and stride are typically identical
|
|
|
619821 |
too, but it doesn't has to be that way. So add and use a new variable
|
|
|
619821 |
(guest_ll) for the guest scanline length. Also rename min_stride to
|
|
|
619821 |
line_bytes to make more clear what it actually is. Finally sprinkle
|
|
|
619821 |
in an assert() to make sure we never use a negative _cmp_bytes again.
|
|
|
619821 |
|
|
|
619821 |
Reported-by: 范祚至(库特) <zuozhi.fzz@alibaba-inc.com>
|
|
|
619821 |
Reviewed-by: P J P <ppandit@redhat.com>
|
|
|
619821 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
619821 |
(cherry picked from commit eb8934b0418b3b1d125edddc4fc334a54334a49b)
|
|
|
619821 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
619821 |
---
|
|
|
619821 |
ui/vnc.c | 15 ++++++++++-----
|
|
|
619821 |
1 file changed, 10 insertions(+), 5 deletions(-)
|
|
|
619821 |
|
|
|
619821 |
diff --git a/ui/vnc.c b/ui/vnc.c
|
|
|
619821 |
index 80b7792..d0ada7e 100644
|
|
|
619821 |
--- a/ui/vnc.c
|
|
|
619821 |
+++ b/ui/vnc.c
|
|
|
619821 |
@@ -2676,7 +2676,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
|
|
|
619821 |
pixman_image_get_width(vd->server));
|
|
|
619821 |
int height = MIN(pixman_image_get_height(vd->guest.fb),
|
|
|
619821 |
pixman_image_get_height(vd->server));
|
|
|
619821 |
- int cmp_bytes, server_stride, min_stride, guest_stride, y = 0;
|
|
|
619821 |
+ int cmp_bytes, server_stride, line_bytes, guest_ll, guest_stride, y = 0;
|
|
|
619821 |
uint8_t *guest_row0 = NULL, *server_row0;
|
|
|
619821 |
VncState *vs;
|
|
|
619821 |
int has_dirty = 0;
|
|
|
619821 |
@@ -2695,17 +2695,21 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
|
|
|
619821 |
* Update server dirty map.
|
|
|
619821 |
*/
|
|
|
619821 |
server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
|
|
|
619821 |
- server_stride = guest_stride = pixman_image_get_stride(vd->server);
|
|
|
619821 |
+ server_stride = guest_stride = guest_ll =
|
|
|
619821 |
+ pixman_image_get_stride(vd->server);
|
|
|
619821 |
cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES,
|
|
|
619821 |
server_stride);
|
|
|
619821 |
if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
|
|
|
619821 |
int width = pixman_image_get_width(vd->server);
|
|
|
619821 |
tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
|
|
|
619821 |
} else {
|
|
|
619821 |
+ int guest_bpp =
|
|
|
619821 |
+ PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb));
|
|
|
619821 |
guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
|
|
|
619821 |
guest_stride = pixman_image_get_stride(vd->guest.fb);
|
|
|
619821 |
+ guest_ll = pixman_image_get_width(vd->guest.fb) * ((guest_bpp + 7) / 8);
|
|
|
619821 |
}
|
|
|
619821 |
- min_stride = MIN(server_stride, guest_stride);
|
|
|
619821 |
+ line_bytes = MIN(server_stride, guest_ll);
|
|
|
619821 |
|
|
|
619821 |
for (;;) {
|
|
|
619821 |
int x;
|
|
|
619821 |
@@ -2736,9 +2740,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
|
|
|
619821 |
if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
|
|
|
619821 |
continue;
|
|
|
619821 |
}
|
|
|
619821 |
- if ((x + 1) * cmp_bytes > min_stride) {
|
|
|
619821 |
- _cmp_bytes = min_stride - x * cmp_bytes;
|
|
|
619821 |
+ if ((x + 1) * cmp_bytes > line_bytes) {
|
|
|
619821 |
+ _cmp_bytes = line_bytes - x * cmp_bytes;
|
|
|
619821 |
}
|
|
|
619821 |
+ assert(_cmp_bytes >= 0);
|
|
|
619821 |
if (memcmp(server_ptr, guest_ptr, _cmp_bytes) == 0) {
|
|
|
619821 |
continue;
|
|
|
619821 |
}
|
|
|
619821 |
--
|
|
|
619821 |
1.8.3.1
|
|
|
619821 |
|