[pve-devel] [PATCH pve-libspice-server] add debian fixes for DSA-3371-1

Wolfgang Link w.link at proxmox.com
Mon Oct 12 14:07:32 CEST 2015


---
 Makefile                                           |   2 +-
 .../0001-worker-validate-correctly-surfaces.patch  | 117 +++++++++++++++++++++
 ...d-double-free-or-double-create-of-surface.patch |  41 ++++++++
 ...efine-a-constant-to-limit-data-from-guest.patch |  42 ++++++++
 ...teger-overflow-causing-large-memory-alloc.patch |  64 +++++++++++
 ...0005-Check-properly-surface-to-be-created.patch |  73 +++++++++++++
 .../patches/0006-Fix-buffer-reading-overflow.patch |  38 +++++++
 ...bit-integer-overflow-in-bitmap_consistent.patch |  46 ++++++++
 ...-Fix-race-condition-on-red_get_clip_rects.patch |  42 ++++++++
 .../patches/0009-Fix-race-in-red_get_image.patch   |  72 +++++++++++++
 ...0010-Fix-race-condition-in-red_get_string.patch |  57 ++++++++++
 ...-overflow-computing-glyph_size-in-red_get.patch |  58 ++++++++++
 ...race-condition-in-red_get_data_chunks_ptr.patch |  66 ++++++++++++
 ...ory-leak-if-red_get_data_chunks_ptr-fails.patch |  75 +++++++++++++
 ...-from-guest-trying-to-allocate-too-much-d.patch | 102 ++++++++++++++++++
 ...ssible-overflows-in-red_get_string-for-32.patch |  36 +++++++
 ...ke-sure-we-can-read-QXLPathSeg-structures.patch |  40 +++++++
 ...condition-copying-segments-in-red_get_pat.patch |  31 ++++++
 ...ta_size-to-be-set-independently-from-data.patch |  24 +++++
 ...k-if-size-from-red_get_data_chunks-don-t-.patch |  31 ++++++
 debian/patches/CVE-2015-3247.patch                 | 117 +++++++++++++++++++++
 debian/patches/CVE-2015-3247.patch~                | 115 ++++++++++++++++++++
 debian/patches/fix-tests-warnings.patch            |  53 ++++++++++
 debian/patches/series                              |  21 ++++
 24 files changed, 1362 insertions(+), 1 deletion(-)
 create mode 100644 debian/patches/0001-worker-validate-correctly-surfaces.patch
 create mode 100644 debian/patches/0002-worker-avoid-double-free-or-double-create-of-surface.patch
 create mode 100644 debian/patches/0003-Define-a-constant-to-limit-data-from-guest.patch
 create mode 100644 debian/patches/0004-Fix-some-integer-overflow-causing-large-memory-alloc.patch
 create mode 100644 debian/patches/0005-Check-properly-surface-to-be-created.patch
 create mode 100644 debian/patches/0006-Fix-buffer-reading-overflow.patch
 create mode 100644 debian/patches/0007-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
 create mode 100644 debian/patches/0008-Fix-race-condition-on-red_get_clip_rects.patch
 create mode 100644 debian/patches/0009-Fix-race-in-red_get_image.patch
 create mode 100644 debian/patches/0010-Fix-race-condition-in-red_get_string.patch
 create mode 100644 debian/patches/0011-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
 create mode 100644 debian/patches/0012-Fix-race-condition-in-red_get_data_chunks_ptr.patch
 create mode 100644 debian/patches/0013-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
 create mode 100644 debian/patches/0014-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
 create mode 100644 debian/patches/0015-Fix-some-possible-overflows-in-red_get_string-for-32.patch
 create mode 100644 debian/patches/0016-Make-sure-we-can-read-QXLPathSeg-structures.patch
 create mode 100644 debian/patches/0017-Avoid-race-condition-copying-segments-in-red_get_pat.patch
 create mode 100644 debian/patches/0018-Prevent-data_size-to-be-set-independently-from-data.patch
 create mode 100644 debian/patches/0019-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
 create mode 100644 debian/patches/CVE-2015-3247.patch
 create mode 100644 debian/patches/CVE-2015-3247.patch~
 create mode 100644 debian/patches/fix-tests-warnings.patch

diff --git a/Makefile b/Makefile
index 5edb51e..cdcc410 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ RELEASE=4.0
 
 PACKAGE=pve-libspice-server1
 PKGVERSION=0.12.5
-PKGRELEASE=1
+PKGRELEASE=2
 
 PKGDIR=spice-${PKGVERSION}
 PKGSRC=${PKGDIR}.tar.bz2
diff --git a/debian/patches/0001-worker-validate-correctly-surfaces.patch b/debian/patches/0001-worker-validate-correctly-surfaces.patch
new file mode 100644
index 0000000..4dea5a2
--- /dev/null
+++ b/debian/patches/0001-worker-validate-correctly-surfaces.patch
@@ -0,0 +1,117 @@
+From dd558bb833254fb49069eca052b92ae1abe3e8ff Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Wed, 9 Sep 2015 12:42:09 +0100
+Subject: [PATCH 01/19] worker: validate correctly surfaces
+
+Do not just give warning and continue to use an invalid index into
+an array.
+
+Resolves: CVE-2015-5260
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_worker.c | 33 ++++++++++++++++++---------------
+ 1 file changed, 18 insertions(+), 15 deletions(-)
+
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -1036,6 +1036,7 @@ typedef struct BitmapData {
+     SpiceRect lossy_rect;
+ } BitmapData;
+ 
++static inline int validate_surface(RedWorker *worker, uint32_t surface_id);
+ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable);
+ static void red_current_flush(RedWorker *worker, int surface_id);
+ #ifdef DRAW_ALL
+@@ -1245,14 +1246,12 @@ static inline int is_primary_surface(Red
+     return FALSE;
+ }
+ 
+-static inline void __validate_surface(RedWorker *worker, uint32_t surface_id)
+-{
+-    spice_warn_if(surface_id >= worker->n_surfaces);
+-}
+-
+ static inline int validate_surface(RedWorker *worker, uint32_t surface_id)
+ {
+-    spice_warn_if(surface_id >= worker->n_surfaces);
++    if SPICE_UNLIKELY(surface_id >= worker->n_surfaces) {
++        spice_warning("invalid surface_id %u", surface_id);
++        return 0;
++    }
+     if (!worker->surfaces[surface_id].context.canvas) {
+         spice_warning("canvas address is %p for %d (and is NULL)\n",
+                    &(worker->surfaces[surface_id].context.canvas), surface_id);
+@@ -4230,12 +4229,14 @@ static inline void red_create_surface(Re
+ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface,
+                                        uint32_t group_id, int loadvm)
+ {
+-    int surface_id;
++    uint32_t surface_id;
+     RedSurface *red_surface;
+     uint8_t *data;
+ 
+     surface_id = surface->surface_id;
+-    __validate_surface(worker, surface_id);
++    if SPICE_UNLIKELY(surface_id >= worker->n_surfaces) {
++        goto exit;
++    }
+ 
+     red_surface = &worker->surfaces[surface_id];
+ 
+@@ -4271,6 +4272,7 @@ static inline void red_process_surface(R
+     default:
+             spice_error("unknown surface command");
+     };
++exit:
+     red_put_surface_cmd(surface);
+     free(surface);
+ }
+@@ -10865,7 +10867,7 @@ void handle_dev_update(void *opaque, voi
+ {
+     RedWorker *worker = opaque;
+     RedWorkerMessageUpdate *msg = payload;
+-    SpiceRect *rect = spice_new0(SpiceRect, 1);
++    SpiceRect *rect;
+     RedSurface *surface;
+     uint32_t surface_id = msg->surface_id;
+     const QXLRect *qxl_area = msg->qxl_area;
+@@ -10873,17 +10875,16 @@ void handle_dev_update(void *opaque, voi
+     QXLRect *qxl_dirty_rects = msg->qxl_dirty_rects;
+     uint32_t clear_dirty_region = msg->clear_dirty_region;
+ 
++    VALIDATE_SURFACE_RET(worker, surface_id);
++
++    rect = spice_new0(SpiceRect, 1);
+     surface = &worker->surfaces[surface_id];
+     red_get_rect_ptr(rect, qxl_area);
+     flush_display_commands(worker);
+ 
+     spice_assert(worker->running);
+ 
+-    if (validate_surface(worker, surface_id)) {
+-        red_update_area(worker, rect, surface_id);
+-    } else {
+-        rendering_incorrect(__func__);
+-    }
++    red_update_area(worker, rect, surface_id);
+     free(rect);
+ 
+     surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects,
+@@ -10922,6 +10923,7 @@ void handle_dev_del_memslot(void *opaque
+  * surface_id == 0, maybe move the assert upward and merge the two functions? */
+ static inline void destroy_surface_wait(RedWorker *worker, int surface_id)
+ {
++    VALIDATE_SURFACE_RET(worker, surface_id);
+     if (!worker->surfaces[surface_id].context.canvas) {
+         return;
+     }
+@@ -11186,6 +11188,7 @@ void handle_dev_create_primary_surface(v
+ 
+ static void dev_destroy_primary_surface(RedWorker *worker, uint32_t surface_id)
+ {
++    VALIDATE_SURFACE_RET(worker, surface_id);
+     spice_warn_if(surface_id != 0);
+ 
+     spice_debug(NULL);
diff --git a/debian/patches/0002-worker-avoid-double-free-or-double-create-of-surface.patch b/debian/patches/0002-worker-avoid-double-free-or-double-create-of-surface.patch
new file mode 100644
index 0000000..09199f4
--- /dev/null
+++ b/debian/patches/0002-worker-avoid-double-free-or-double-create-of-surface.patch
@@ -0,0 +1,41 @@
+From 097c638b121e595d9daf79285c447088027a58e2 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Wed, 9 Sep 2015 12:45:06 +0100
+Subject: [PATCH 02/19] worker: avoid double free or double create of surfaces
+
+A driver can overwrite surface state creating a surface with the same
+id of a previous one.
+Also can try to destroy surfaces that are not created.
+Both requests cause invalid internal states that could lead to crashes
+or memory corruptions.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_worker.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -4246,6 +4246,10 @@ static inline void red_process_surface(R
+         int32_t stride = surface->u.surface_create.stride;
+         int reloaded_surface = loadvm || (surface->flags & QXL_SURF_FLAG_KEEP_DATA);
+ 
++        if (red_surface->refs) {
++            spice_warning("avoiding creating a surface twice");
++            break;
++        }
+         data = surface->u.surface_create.data;
+         if (stride < 0) {
+             data -= (int32_t)(stride * (height - 1));
+@@ -4259,7 +4263,10 @@ static inline void red_process_surface(R
+         break;
+     }
+     case QXL_SURFACE_CMD_DESTROY:
+-        spice_warn_if(!red_surface->context.canvas);
++        if (!red_surface->refs) {
++            spice_warning("avoiding destroying a surface twice");
++            break;
++        }
+         set_surface_release_info(worker, surface_id, 0, surface->release_info, group_id);
+         red_handle_depends_on_target_surface(worker, surface_id);
+         /* note that red_handle_depends_on_target_surface must be called before red_current_clear.
diff --git a/debian/patches/0003-Define-a-constant-to-limit-data-from-guest.patch b/debian/patches/0003-Define-a-constant-to-limit-data-from-guest.patch
new file mode 100644
index 0000000..2f4bd0f
--- /dev/null
+++ b/debian/patches/0003-Define-a-constant-to-limit-data-from-guest.patch
@@ -0,0 +1,42 @@
+From 0205a6ce63f50af9eda03f14d93b3a2517c42fae Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 11:58:11 +0100
+Subject: [PATCH 03/19] Define a constant to limit data from guest.
+
+This limit will prevent guest trying to do nasty things and DoS to host.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 5b1befa..3ffa57b 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -21,11 +21,22 @@
+ 
+ #include <stdbool.h>
+ #include <inttypes.h>
++#include <glib.h>
+ #include "common/lz_common.h"
+ #include "red_common.h"
+ #include "red_memslots.h"
+ #include "red_parse_qxl.h"
+ 
++/* Max size in bytes for any data field used in a QXL command.
++ * This will for example be useful to prevent the guest from saturating the
++ * host memory if it tries to send overlapping chunks.
++ * This value should be big enough for all requests but limited
++ * to 32 bits. Even better if it fits on 31 bits to detect integer overflows.
++ */
++#define MAX_DATA_CHUNK 0x7ffffffflu
++
++G_STATIC_ASSERT(MAX_DATA_CHUNK <= G_MAXINT32);
++
+ #if 0
+ static void hexdump_qxl(RedMemSlotInfo *slots, int group_id,
+                         QXLPHYSICAL addr, uint8_t bytes)
+-- 
+2.6.1
+
diff --git a/debian/patches/0004-Fix-some-integer-overflow-causing-large-memory-alloc.patch b/debian/patches/0004-Fix-some-integer-overflow-causing-large-memory-alloc.patch
new file mode 100644
index 0000000..0d481a4
--- /dev/null
+++ b/debian/patches/0004-Fix-some-integer-overflow-causing-large-memory-alloc.patch
@@ -0,0 +1,64 @@
+From ac5f64a80ae637742ed95fd6c98f66281b3e15c6 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Thu, 17 Sep 2015 15:00:22 +0100
+Subject: [PATCH 04/19] Fix some integer overflow causing large memory
+ allocations
+
+Prevent integer overflow when computing image sizes.
+Image index computations are done using 32 bit so this can cause easily
+security issues. MAX_DATA_CHUNK is larger than the virtual
+card limit, so this is not going to cause change in behaviours.
+Comparing size calculation results with MAX_DATA_CHUNK will allow us to
+catch overflows.
+Prevent guest from allocating large amount of memory.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -384,7 +384,7 @@ static SpiceImage *red_get_image(RedMemS
+     QXLImage *qxl;
+     SpiceImage *red = NULL;
+     SpicePalette *rp = NULL;
+-    size_t bitmap_size, size;
++    uint64_t bitmap_size, size;
+     uint8_t qxl_flags;
+     int error;
+ 
+@@ -460,7 +460,10 @@ static SpiceImage *red_get_image(RedMemS
+             red->u.bitmap.palette = rp;
+             red->u.bitmap.palette_id = rp->unique;
+         }
+-        bitmap_size = red->u.bitmap.y * abs(red->u.bitmap.stride);
++        bitmap_size = (uint64_t) red->u.bitmap.y * abs(red->u.bitmap.stride);
++        if (bitmap_size > MAX_DATA_CHUNK) {
++            goto error;
++        }
+         if (qxl_flags & QXL_BITMAP_DIRECT) {
+             red->u.bitmap.data = red_get_image_data_flat(slots, group_id,
+                                                          qxl->bitmap.data,
+@@ -1221,7 +1224,7 @@ int red_get_surface_cmd(RedMemSlotInfo *
+                         RedSurfaceCmd *red, QXLPHYSICAL addr)
+ {
+     QXLSurfaceCmd *qxl;
+-    size_t size;
++    uint64_t size;
+     int error;
+ 
+     qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
+@@ -1241,7 +1244,11 @@ int red_get_surface_cmd(RedMemSlotInfo *
+         red->u.surface_create.width  = qxl->u.surface_create.width;
+         red->u.surface_create.height = qxl->u.surface_create.height;
+         red->u.surface_create.stride = qxl->u.surface_create.stride;
+-        size = red->u.surface_create.height * abs(red->u.surface_create.stride);
++        /* the multiplication can overflow, also abs(-2^31) may return a negative value */
++        size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride);
++        if (size > MAX_DATA_CHUNK || red->u.surface_create.stride == G_MININT32) {
++            return 1;
++        }
+         red->u.surface_create.data =
+             (uint8_t*)get_virt(slots, qxl->u.surface_create.data, size, group_id, &error);
+         if (error) {
diff --git a/debian/patches/0005-Check-properly-surface-to-be-created.patch b/debian/patches/0005-Check-properly-surface-to-be-created.patch
new file mode 100644
index 0000000..2e0ae6c
--- /dev/null
+++ b/debian/patches/0005-Check-properly-surface-to-be-created.patch
@@ -0,0 +1,73 @@
+From 1eb93baa3c594e1214b1c92bbad8a06e9c7e2d12 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 16:02:59 +0100
+Subject: [PATCH 05/19] Check properly surface to be created
+
+Check format is valid.
+Check stride is at least the size of required bytes for a row.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 35 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 34 insertions(+), 1 deletion(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -1220,12 +1220,30 @@ void red_put_message(RedMessage *red)
+     /* nothing yet */
+ }
+ 
++static unsigned int surface_format_to_bpp(uint32_t format)
++{
++    switch (format) {
++    case SPICE_SURFACE_FMT_1_A:
++        return 1;
++    case SPICE_SURFACE_FMT_8_A:
++        return 8;
++    case SPICE_SURFACE_FMT_16_555:
++    case SPICE_SURFACE_FMT_16_565:
++        return 16;
++    case SPICE_SURFACE_FMT_32_xRGB:
++    case SPICE_SURFACE_FMT_32_ARGB:
++        return 32;
++    }
++    return 0;
++}
++
+ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+                         RedSurfaceCmd *red, QXLPHYSICAL addr)
+ {
+     QXLSurfaceCmd *qxl;
+     uint64_t size;
+     int error;
++    unsigned int bpp;
+ 
+     qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
+                                     &error);
+@@ -1244,9 +1262,24 @@ int red_get_surface_cmd(RedMemSlotInfo *
+         red->u.surface_create.width  = qxl->u.surface_create.width;
+         red->u.surface_create.height = qxl->u.surface_create.height;
+         red->u.surface_create.stride = qxl->u.surface_create.stride;
++        bpp = surface_format_to_bpp(red->u.surface_create.format);
++
++        /* check if format is valid */
++        if (!bpp) {
++            return 1;
++        }
++
++        /* check stride is larger than required bytes */
++        size = ((uint64_t) red->u.surface_create.width * bpp + 7u) / 8u;
++        /* the uint32_t conversion is here to avoid problems with -2^31 value */
++        if (red->u.surface_create.stride == G_MININT32
++            || size > (uint32_t) abs(red->u.surface_create.stride)) {
++            return 1;
++        }
++
+         /* the multiplication can overflow, also abs(-2^31) may return a negative value */
+         size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride);
+-        if (size > MAX_DATA_CHUNK || red->u.surface_create.stride == G_MININT32) {
++        if (size > MAX_DATA_CHUNK) {
+             return 1;
+         }
+         red->u.surface_create.data =
diff --git a/debian/patches/0006-Fix-buffer-reading-overflow.patch b/debian/patches/0006-Fix-buffer-reading-overflow.patch
new file mode 100644
index 0000000..c07eab2
--- /dev/null
+++ b/debian/patches/0006-Fix-buffer-reading-overflow.patch
@@ -0,0 +1,38 @@
+From 68a742aaa8d692940ac15d021799b702412887e5 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 10:00:37 +0100
+Subject: [PATCH 06/19] Fix buffer reading overflow
+
+Not security risk as just for read.
+However, this could be used to attempt integer overflows in the
+following lines.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index bdd5917..e2f95e4 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -361,7 +361,14 @@ static const int MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[] = {0, 1, 1, 4, 4, 8, 16, 24,
+ 
+ static int bitmap_consistent(SpiceBitmap *bitmap)
+ {
+-    int bpp = MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[bitmap->format];
++    int bpp;
++
++    if (bitmap->format >= SPICE_N_ELEMENTS(MAP_BITMAP_FMT_TO_BITS_PER_PIXEL)) {
++        spice_warning("wrong format specified for image\n");
++        return FALSE;
++    }
++
++    bpp = MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[bitmap->format];
+ 
+     if (bitmap->stride < ((bitmap->x * bpp + 7) / 8)) {
+         spice_warning("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
+-- 
+2.6.1
+
diff --git a/debian/patches/0007-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch b/debian/patches/0007-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
new file mode 100644
index 0000000..cbe6029
--- /dev/null
+++ b/debian/patches/0007-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
@@ -0,0 +1,46 @@
+From 0f58e9da56e0cbbe4349eefcbb300b6f285e0423 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 13:09:35 +0100
+Subject: [PATCH 07/19] Prevent 32 bit integer overflow in bitmap_consistent
+
+The overflow may lead to buffer overflow as the row size computed from
+width (bitmap->x) can be bigger than the size in bytes (bitmap->stride).
+This can make spice-server accept the invalid sizes.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index e2f95e4..40c1c99 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -357,11 +357,12 @@ static const char *bitmap_format_to_string(int format)
+     return "unknown";
+ }
+ 
+-static const int MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[] = {0, 1, 1, 4, 4, 8, 16, 24, 32, 32, 8};
++static const unsigned int MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[] =
++    {0, 1, 1, 4, 4, 8, 16, 24, 32, 32, 8};
+ 
+ static int bitmap_consistent(SpiceBitmap *bitmap)
+ {
+-    int bpp;
++    unsigned int bpp;
+ 
+     if (bitmap->format >= SPICE_N_ELEMENTS(MAP_BITMAP_FMT_TO_BITS_PER_PIXEL)) {
+         spice_warning("wrong format specified for image\n");
+@@ -370,7 +371,7 @@ static int bitmap_consistent(SpiceBitmap *bitmap)
+ 
+     bpp = MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[bitmap->format];
+ 
+-    if (bitmap->stride < ((bitmap->x * bpp + 7) / 8)) {
++    if (bitmap->stride < (((uint64_t) bitmap->x * bpp + 7u) / 8u)) {
+         spice_warning("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
+                     bitmap->stride, bitmap->x, bpp,
+                     bitmap_format_to_string(bitmap->format),
+-- 
+2.6.1
+
diff --git a/debian/patches/0008-Fix-race-condition-on-red_get_clip_rects.patch b/debian/patches/0008-Fix-race-condition-on-red_get_clip_rects.patch
new file mode 100644
index 0000000..9f8a763
--- /dev/null
+++ b/debian/patches/0008-Fix-race-condition-on-red_get_clip_rects.patch
@@ -0,0 +1,42 @@
+From 3dfd1a08286d524a742d51952595fcfb6f0c6f1b Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 10:01:51 +0100
+Subject: [PATCH 08/19] Fix race condition on red_get_clip_rects
+
+Do not read multiple time an array size that can be changed.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 40c1c99..a9f3ca1 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -273,6 +273,7 @@ static SpiceClipRects *red_get_clip_rects(RedMemSlotInfo *slots, int group_id,
+     size_t size;
+     int i;
+     int error;
++    uint32_t num_rects;
+ 
+     qxl = (QXLClipRects *)get_virt(slots, addr, sizeof(*qxl), group_id, &error);
+     if (error) {
+@@ -284,9 +285,10 @@ static SpiceClipRects *red_get_clip_rects(RedMemSlotInfo *slots, int group_id,
+     data = red_linearize_chunk(&chunks, size, &free_data);
+     red_put_data_chunks(&chunks);
+ 
+-    spice_assert(qxl->num_rects * sizeof(QXLRect) == size);
+-    red = spice_malloc(sizeof(*red) + qxl->num_rects * sizeof(SpiceRect));
+-    red->num_rects = qxl->num_rects;
++    num_rects = qxl->num_rects;
++    spice_assert(num_rects * sizeof(QXLRect) == size);
++    red = spice_malloc(sizeof(*red) + num_rects * sizeof(SpiceRect));
++    red->num_rects = num_rects;
+ 
+     start = (QXLRect*)data;
+     for (i = 0; i < red->num_rects; i++) {
+-- 
+2.6.1
+
diff --git a/debian/patches/0009-Fix-race-in-red_get_image.patch b/debian/patches/0009-Fix-race-in-red_get_image.patch
new file mode 100644
index 0000000..370c0cd
--- /dev/null
+++ b/debian/patches/0009-Fix-race-in-red_get_image.patch
@@ -0,0 +1,72 @@
+From 9235c84e0fbbf5c19305e82fc1607393b35b74ef Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 10:04:10 +0100
+Subject: [PATCH 09/19] Fix race in red_get_image
+
+Do not read multiple times data from guest as this could be changed
+by other vcpu threads.
+This causes races and security problems if these data are used for
+buffer allocation or checks.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -397,6 +397,7 @@ static SpiceImage *red_get_image(RedMemS
+     uint64_t bitmap_size, size;
+     uint8_t qxl_flags;
+     int error;
++    QXLPHYSICAL palette;
+ 
+     if (addr == 0) {
+         return NULL;
+@@ -422,12 +423,16 @@ static SpiceImage *red_get_image(RedMemS
+     switch (red->descriptor.type) {
+     case SPICE_IMAGE_TYPE_BITMAP:
+         red->u.bitmap.format = qxl->bitmap.format;
+-        if (!bitmap_fmt_is_rgb(qxl->bitmap.format) && !qxl->bitmap.palette && !is_mask) {
++        red->u.bitmap.x      = qxl->bitmap.x;
++        red->u.bitmap.y      = qxl->bitmap.y;
++        red->u.bitmap.stride = qxl->bitmap.stride;
++        palette = qxl->bitmap.palette;
++        if (!bitmap_fmt_is_rgb(red->u.bitmap.format) && !palette && !is_mask) {
+             spice_warning("guest error: missing palette on bitmap format=%d\n",
+                           red->u.bitmap.format);
+             goto error;
+         }
+-        if (qxl->bitmap.x == 0 || qxl->bitmap.y == 0) {
++        if (red->u.bitmap.x == 0 || red->u.bitmap.y == 0) {
+             spice_warning("guest error: zero area bitmap\n");
+             goto error;
+         }
+@@ -435,23 +440,20 @@ static SpiceImage *red_get_image(RedMemS
+         if (qxl_flags & QXL_BITMAP_TOP_DOWN) {
+             red->u.bitmap.flags = SPICE_BITMAP_FLAGS_TOP_DOWN;
+         }
+-        red->u.bitmap.x      = qxl->bitmap.x;
+-        red->u.bitmap.y      = qxl->bitmap.y;
+-        red->u.bitmap.stride = qxl->bitmap.stride;
+         if (!bitmap_consistent(&red->u.bitmap)) {
+             goto error;
+         }
+-        if (qxl->bitmap.palette) {
++        if (palette) {
+             QXLPalette *qp;
+             int i, num_ents;
+-            qp = (QXLPalette *)get_virt(slots, qxl->bitmap.palette,
++            qp = (QXLPalette *)get_virt(slots, palette,
+                                         sizeof(*qp), group_id, &error);
+             if (error) {
+                 goto error;
+             }
+             num_ents = qp->num_ents;
+             if (!validate_virt(slots, (intptr_t)qp->ents,
+-                               get_memslot_id(slots, qxl->bitmap.palette),
++                               get_memslot_id(slots, palette),
+                                num_ents * sizeof(qp->ents[0]), group_id)) {
+                 goto error;
+             }
diff --git a/debian/patches/0010-Fix-race-condition-in-red_get_string.patch b/debian/patches/0010-Fix-race-condition-in-red_get_string.patch
new file mode 100644
index 0000000..fa6e9cc
--- /dev/null
+++ b/debian/patches/0010-Fix-race-condition-in-red_get_string.patch
@@ -0,0 +1,57 @@
+From dfaedec7890069b35f513e4a8ab4071ca54259ff Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 10:05:20 +0100
+Subject: [PATCH 10/19] Fix race condition in red_get_string
+
+Do not read multiple time an array size that can be changed.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -810,6 +810,7 @@ static SpiceString *red_get_string(RedMe
+     size_t chunk_size, qxl_size, red_size, glyph_size;
+     int glyphs, bpp = 0, i;
+     int error;
++    uint16_t qxl_flags, qxl_length;
+ 
+     qxl = (QXLString *)get_virt(slots, addr, sizeof(*qxl), group_id, &error);
+     if (error) {
+@@ -826,13 +827,15 @@ static SpiceString *red_get_string(RedMe
+     red_put_data_chunks(&chunks);
+ 
+     qxl_size = qxl->data_size;
++    qxl_flags = qxl->flags;
++    qxl_length = qxl->length;
+     spice_assert(chunk_size == qxl_size);
+ 
+-    if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A1) {
++    if (qxl_flags & SPICE_STRING_FLAGS_RASTER_A1) {
+         bpp = 1;
+-    } else if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A4) {
++    } else if (qxl_flags & SPICE_STRING_FLAGS_RASTER_A4) {
+         bpp = 4;
+-    } else if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A8) {
++    } else if (qxl_flags & SPICE_STRING_FLAGS_RASTER_A8) {
+         bpp = 8;
+     }
+     spice_assert(bpp != 0);
+@@ -849,11 +852,11 @@ static SpiceString *red_get_string(RedMe
+         start = (QXLRasterGlyph*)(&start->data[glyph_size]);
+     }
+     spice_assert(start <= end);
+-    spice_assert(glyphs == qxl->length);
++    spice_assert(glyphs == qxl_length);
+ 
+     red = spice_malloc(red_size);
+-    red->length = qxl->length;
+-    red->flags = qxl->flags;
++    red->length = qxl_length;
++    red->flags = qxl_flags;
+ 
+     start = (QXLRasterGlyph*)data;
+     end = (QXLRasterGlyph*)(data + chunk_size);
diff --git a/debian/patches/0011-Fix-integer-overflow-computing-glyph_size-in-red_get.patch b/debian/patches/0011-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
new file mode 100644
index 0000000..48dbb5b
--- /dev/null
+++ b/debian/patches/0011-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
@@ -0,0 +1,58 @@
+From caec52dc77af6ebdac3219a1b10fe2293af21208 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 10:13:24 +0100
+Subject: [PATCH 11/19] Fix integer overflow computing glyph_size in
+ red_get_string
+
+If bpp is int the formula can lead to weird overflows. width and height
+are uint16_t so the formula is:
+
+  size_t = u16 * (u16 * int + const_int) / const_int;
+
+so it became
+
+  size_t = (int) u16 * ((int) u16 * int + const_int) / const_int;
+
+However the (int) u16 * (int) u16 can then became negative to overflow.
+Under 64 bit architectures size_t is 64 and int usually 32 so converting
+this negative 32 bit number to a unsigned 64 bit lead to a very big
+number as the signed is extended and then converted to unsigned.
+Using unsigned arithmetic prevent extending the sign.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -808,7 +808,9 @@ static SpiceString *red_get_string(RedMe
+     uint8_t *data;
+     bool free_data;
+     size_t chunk_size, qxl_size, red_size, glyph_size;
+-    int glyphs, bpp = 0, i;
++    int glyphs, i;
++    /* use unsigned to prevent integer overflow in multiplication below */
++    unsigned int bpp = 0;
+     int error;
+     uint16_t qxl_flags, qxl_length;
+ 
+@@ -847,7 +849,7 @@ static SpiceString *red_get_string(RedMe
+     while (start < end) {
+         spice_assert((QXLRasterGlyph*)(&start->data[0]) <= end);
+         glyphs++;
+-        glyph_size = start->height * ((start->width * bpp + 7) / 8);
++        glyph_size = start->height * ((start->width * bpp + 7u) / 8u);
+         red_size += sizeof(SpiceRasterGlyph *) + SPICE_ALIGN(sizeof(SpiceRasterGlyph) + glyph_size, 4);
+         start = (QXLRasterGlyph*)(&start->data[glyph_size]);
+     }
+@@ -868,7 +870,7 @@ static SpiceString *red_get_string(RedMe
+         glyph->height = start->height;
+         red_get_point_ptr(&glyph->render_pos, &start->render_pos);
+         red_get_point_ptr(&glyph->glyph_origin, &start->glyph_origin);
+-        glyph_size = glyph->height * ((glyph->width * bpp + 7) / 8);
++        glyph_size = glyph->height * ((glyph->width * bpp + 7u) / 8u);
+         spice_assert((QXLRasterGlyph*)(&start->data[glyph_size]) <= end);
+         memcpy(glyph->data, start->data, glyph_size);
+         start = (QXLRasterGlyph*)(&start->data[glyph_size]);
diff --git a/debian/patches/0012-Fix-race-condition-in-red_get_data_chunks_ptr.patch b/debian/patches/0012-Fix-race-condition-in-red_get_data_chunks_ptr.patch
new file mode 100644
index 0000000..b696bc0
--- /dev/null
+++ b/debian/patches/0012-Fix-race-condition-in-red_get_data_chunks_ptr.patch
@@ -0,0 +1,66 @@
+From 3738478ed7065fe05f3ee4848f8a7fcdf40aa920 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 12:12:19 +0100
+Subject: [PATCH 12/19] Fix race condition in red_get_data_chunks_ptr
+
+Do not read multiple times data from guest as this can be changed by
+other guest vcpus. This causes races and security problems if these
+data are used for buffer allocation or checks.
+
+Actually, the 'data' member can't change during read as it is just a
+pointer to a fixed array contained in qxl. However, this change will
+make it clear that there can be no race condition.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index cfa21f9..2863ae2 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -102,30 +102,33 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
+     RedDataChunk *red_prev;
+     size_t data_size = 0;
+     int error;
++    QXLPHYSICAL next_chunk;
+ 
+     red->data_size = qxl->data_size;
+     data_size += red->data_size;
+-    if (!validate_virt(slots, (intptr_t)qxl->data, memslot_id, red->data_size, group_id)) {
++    red->data = qxl->data;
++    if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
++        red->data = NULL;
+         return 0;
+     }
+-    red->data = qxl->data;
+     red->prev_chunk = NULL;
+ 
+-    while (qxl->next_chunk) {
++    while ((next_chunk = qxl->next_chunk) != 0) {
+         red_prev = red;
+         red = spice_new(RedDataChunk, 1);
+-        memslot_id = get_memslot_id(slots, qxl->next_chunk);
+-        qxl = (QXLDataChunk *)get_virt(slots, qxl->next_chunk, sizeof(*qxl), group_id,
++        memslot_id = get_memslot_id(slots, next_chunk);
++        qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
+                                       &error);
+         if (error) {
+             return 0;
+         }
+         red->data_size = qxl->data_size;
+         data_size += red->data_size;
+-        if (!validate_virt(slots, (intptr_t)qxl->data, memslot_id, red->data_size, group_id)) {
++        red->data = qxl->data;
++        if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
++            red->data = NULL;
+             return 0;
+         }
+-        red->data = qxl->data;
+         red->prev_chunk = red_prev;
+         red_prev->next_chunk = red;
+     }
+-- 
+2.6.1
+
diff --git a/debian/patches/0013-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch b/debian/patches/0013-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
new file mode 100644
index 0000000..a9eb640
--- /dev/null
+++ b/debian/patches/0013-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
@@ -0,0 +1,75 @@
+From f3605979ce3b33d60c33b59334b53618e6d8662a Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 12:14:55 +0100
+Subject: [PATCH 13/19] Prevent memory leak if red_get_data_chunks_ptr fails
+
+Free linked list if client tries to do nasty things
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 2863ae2..f425869 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -107,34 +107,43 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
+     red->data_size = qxl->data_size;
+     data_size += red->data_size;
+     red->data = qxl->data;
++    red->prev_chunk = red->next_chunk = NULL;
+     if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
+         red->data = NULL;
+         return 0;
+     }
+-    red->prev_chunk = NULL;
+ 
+     while ((next_chunk = qxl->next_chunk) != 0) {
+         red_prev = red;
+-        red = spice_new(RedDataChunk, 1);
++        red = spice_new0(RedDataChunk, 1);
++        red->prev_chunk = red_prev;
++        red_prev->next_chunk = red;
++
+         memslot_id = get_memslot_id(slots, next_chunk);
+         qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
+                                       &error);
+-        if (error) {
+-            return 0;
+-        }
++        if (error)
++            goto error;
+         red->data_size = qxl->data_size;
+         data_size += red->data_size;
+         red->data = qxl->data;
+-        if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
+-            red->data = NULL;
+-            return 0;
+-        }
+-        red->prev_chunk = red_prev;
+-        red_prev->next_chunk = red;
++        if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id))
++            goto error;
+     }
+ 
+     red->next_chunk = NULL;
+     return data_size;
++
++error:
++    while (red->prev_chunk) {
++        red_prev = red->prev_chunk;
++        free(red);
++        red = red_prev;
++    }
++    red->data_size = 0;
++    red->next_chunk = NULL;
++    red->data = NULL;
++    return 0;
+ }
+ 
+ static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,
+-- 
+2.6.1
+
diff --git a/debian/patches/0014-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch b/debian/patches/0014-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
new file mode 100644
index 0000000..1df492b
--- /dev/null
+++ b/debian/patches/0014-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
@@ -0,0 +1,102 @@
+From 7d69184037d0abb4fcfd5625c765b822aa458808 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 12:28:54 +0100
+Subject: [PATCH 14/19] Prevent DoS from guest trying to allocate too much data
+ on host for chunks
+
+Limit number of chunks to a given amount to avoid guest trying to
+allocate too much memory. Using circular or nested chunks lists
+guest could try to allocate huge amounts of memory.
+Considering the list can be infinite and guest can change data this
+also prevents strange security attacks from guest.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 41 insertions(+), 8 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index f425869..5513e82 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -37,6 +37,13 @@
+ 
+ G_STATIC_ASSERT(MAX_DATA_CHUNK <= G_MAXINT32);
+ 
++/* Limit number of chunks.
++ * The guest can attempt to make host allocate too much memory
++ * just with a large number of small chunks.
++ * Prevent that the chunk list take more memory than the data itself.
++ */
++#define MAX_CHUNKS (MAX_DATA_CHUNK/1024u)
++
+ #if 0
+ static void hexdump_qxl(RedMemSlotInfo *slots, int group_id,
+                         QXLPHYSICAL addr, uint8_t bytes)
+@@ -100,9 +107,11 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
+                                       RedDataChunk *red, QXLDataChunk *qxl)
+ {
+     RedDataChunk *red_prev;
+-    size_t data_size = 0;
++    uint64_t data_size = 0;
++    uint32_t chunk_data_size;
+     int error;
+     QXLPHYSICAL next_chunk;
++    unsigned num_chunks = 0;
+ 
+     red->data_size = qxl->data_size;
+     data_size += red->data_size;
+@@ -114,19 +123,43 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
+     }
+ 
+     while ((next_chunk = qxl->next_chunk) != 0) {
++        /* somebody is trying to use too much memory using a lot of chunks.
++         * Or made a circular list of chunks
++         */
++        if (++num_chunks >= MAX_CHUNKS) {
++            spice_warning("data split in too many chunks, avoiding DoS\n");
++            goto error;
++        }
++
++        memslot_id = get_memslot_id(slots, next_chunk);
++        qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl),
++                                       group_id, &error);
++        if (error)
++            goto error;
++
++        /* do not waste space for empty chunks.
++         * This could be just a driver issue or an attempt
++         * to allocate too much memory or a circular list.
++         * All above cases are handled by the check for number
++         * of chunks.
++         */
++        chunk_data_size = qxl->data_size;
++        if (chunk_data_size == 0)
++            continue;
++
+         red_prev = red;
+         red = spice_new0(RedDataChunk, 1);
++        red->data_size = chunk_data_size;
+         red->prev_chunk = red_prev;
++        red->data = qxl->data;
+         red_prev->next_chunk = red;
+ 
+-        memslot_id = get_memslot_id(slots, next_chunk);
+-        qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
+-                                      &error);
+-        if (error)
++        data_size += chunk_data_size;
++        /* this can happen if client is sending nested chunks */
++        if (data_size > MAX_DATA_CHUNK) {
++            spice_warning("too much data inside chunks, avoiding DoS\n");
+             goto error;
+-        red->data_size = qxl->data_size;
+-        data_size += red->data_size;
+-        red->data = qxl->data;
++        }
+         if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id))
+             goto error;
+     }
+-- 
+2.6.1
+
diff --git a/debian/patches/0015-Fix-some-possible-overflows-in-red_get_string-for-32.patch b/debian/patches/0015-Fix-some-possible-overflows-in-red_get_string-for-32.patch
new file mode 100644
index 0000000..979bfe4
--- /dev/null
+++ b/debian/patches/0015-Fix-some-possible-overflows-in-red_get_string-for-32.patch
@@ -0,0 +1,36 @@
+From a447c4f2ac19a1fa36330ffc90ee70b953b82050 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 8 Sep 2015 13:06:03 +0100
+Subject: [PATCH 15/19] Fix some possible overflows in red_get_string for 32
+ bit
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -896,6 +896,11 @@ static SpiceString *red_get_string(RedMe
+         glyphs++;
+         glyph_size = start->height * ((start->width * bpp + 7u) / 8u);
+         red_size += sizeof(SpiceRasterGlyph *) + SPICE_ALIGN(sizeof(SpiceRasterGlyph) + glyph_size, 4);
++        /* do the test correctly, we know end - start->data[0] cannot
++         * overflow, don't use start->data[glyph_size] to test for
++         * buffer overflow as this on 32 bit can cause overflow
++         * on the pointer arithmetic */
++        spice_assert(glyph_size <= (char*) end - (char*) &start->data[0]);
+         start = (QXLRasterGlyph*)(&start->data[glyph_size]);
+     }
+     spice_assert(start <= end);
+@@ -916,7 +921,8 @@ static SpiceString *red_get_string(RedMe
+         red_get_point_ptr(&glyph->render_pos, &start->render_pos);
+         red_get_point_ptr(&glyph->glyph_origin, &start->glyph_origin);
+         glyph_size = glyph->height * ((glyph->width * bpp + 7u) / 8u);
+-        spice_assert((QXLRasterGlyph*)(&start->data[glyph_size]) <= end);
++        /* see above for similar test */
++        spice_assert(glyph_size <= (char*) end - (char*) &start->data[0]);
+         memcpy(glyph->data, start->data, glyph_size);
+         start = (QXLRasterGlyph*)(&start->data[glyph_size]);
+         glyph = (SpiceRasterGlyph*)
diff --git a/debian/patches/0016-Make-sure-we-can-read-QXLPathSeg-structures.patch b/debian/patches/0016-Make-sure-we-can-read-QXLPathSeg-structures.patch
new file mode 100644
index 0000000..b34f9a9
--- /dev/null
+++ b/debian/patches/0016-Make-sure-we-can-read-QXLPathSeg-structures.patch
@@ -0,0 +1,40 @@
+From 2693e0497e5626642250cff47a59b3b4b2cd432d Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 15 Sep 2015 16:25:17 +0100
+Subject: [PATCH 16/19] Make sure we can read QXLPathSeg structures
+
+start pointer points to a QXLPathSeg structure.
+Before reading from the structure, make sure the structure is contained
+in the memory range checked.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index f21bfa5..281faad 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -256,7 +256,7 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
+ 
+     start = (QXLPathSeg*)data;
+     end = (QXLPathSeg*)(data + size);
+-    while (start < end) {
++    while (start+1 < end) {
+         n_segments++;
+         count = start->count;
+         segment_size = sizeof(SpicePathSeg) + count * sizeof(SpicePointFix);
+@@ -272,7 +272,7 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
+     seg = (SpicePathSeg*)&red->segments[n_segments];
+     n_segments = 0;
+     mem_size2 = sizeof(*red);
+-    while (start < end) {
++    while (start+1 < end) {
+         red->segments[n_segments++] = seg;
+         count = start->count;
+ 
+-- 
+2.6.1
+
diff --git a/debian/patches/0017-Avoid-race-condition-copying-segments-in-red_get_pat.patch b/debian/patches/0017-Avoid-race-condition-copying-segments-in-red_get_pat.patch
new file mode 100644
index 0000000..06b6908
--- /dev/null
+++ b/debian/patches/0017-Avoid-race-condition-copying-segments-in-red_get_pat.patch
@@ -0,0 +1,31 @@
+From 2b6695f1222f68690ea230e4e37ded7e07188f06 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 15 Sep 2015 16:38:23 +0100
+Subject: [PATCH 17/19] Avoid race condition copying segments in red_get_path
+
+The guest can attempt to increase the number of segments while
+spice-server is reading them.
+Make sure we don't copy more then the allocated segments.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+Acked-by: Christophe Fergeau <cfergeau at redhat.com>
+---
+ server/red_parse_qxl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 281faad..c7f8650 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -272,7 +272,7 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
+     seg = (SpicePathSeg*)&red->segments[n_segments];
+     n_segments = 0;
+     mem_size2 = sizeof(*red);
+-    while (start+1 < end) {
++    while (start+1 < end && n_segments < red->num_segments) {
+         red->segments[n_segments++] = seg;
+         count = start->count;
+ 
+-- 
+2.6.1
+
diff --git a/debian/patches/0018-Prevent-data_size-to-be-set-independently-from-data.patch b/debian/patches/0018-Prevent-data_size-to-be-set-independently-from-data.patch
new file mode 100644
index 0000000..614f237
--- /dev/null
+++ b/debian/patches/0018-Prevent-data_size-to-be-set-independently-from-data.patch
@@ -0,0 +1,24 @@
+From b3be589ab3b32af3e470a9dec19a61fb086f72fc Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Thu, 17 Sep 2015 14:28:36 +0100
+Subject: [PATCH 18/19] Prevent data_size to be set independently from data
+
+There was not check for data_size field so one could set data to
+a small set of data and data_size much bigger than size of data
+leading to buffer overflow.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -1392,6 +1392,7 @@ static int red_get_cursor(RedMemSlotInfo
+     size = red_get_data_chunks_ptr(slots, group_id,
+                                    get_memslot_id(slots, addr),
+                                    &chunks, &qxl->chunk);
++    red->data_size = MIN(red->data_size, size);
+     data = red_linearize_chunk(&chunks, size, &free_data);
+     red_put_data_chunks(&chunks);
+     if (free_data) {
diff --git a/debian/patches/0019-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch b/debian/patches/0019-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
new file mode 100644
index 0000000..a9aa966
--- /dev/null
+++ b/debian/patches/0019-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
@@ -0,0 +1,31 @@
+From 6e3547f8b192f5b01d478ca222bf46736f5c700c Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Thu, 17 Sep 2015 15:01:05 +0100
+Subject: [PATCH 19/19] Prevent leak if size from red_get_data_chunks don't
+ match in red_get_image
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_parse_qxl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: spice/server/red_parse_qxl.c
+===================================================================
+--- spice.orig/server/red_parse_qxl.c
++++ spice/server/red_parse_qxl.c
+@@ -530,6 +530,7 @@ static SpiceImage *red_get_image(RedMemS
+                                        &chunks, qxl->bitmap.data);
+             spice_assert(size == bitmap_size);
+             if (size != bitmap_size) {
++                red_put_data_chunks(&chunks);
+                 goto error;
+             }
+             red->u.bitmap.data = red_get_image_data_chunked(slots, group_id,
+@@ -550,6 +551,7 @@ static SpiceImage *red_get_image(RedMemS
+                                        &chunks, (QXLDataChunk *)qxl->quic.data);
+         spice_assert(size == red->u.quic.data_size);
+         if (size != red->u.quic.data_size) {
++            red_put_data_chunks(&chunks);
+             goto error;
+         }
+         red->u.quic.data = red_get_image_data_chunked(slots, group_id,
diff --git a/debian/patches/CVE-2015-3247.patch b/debian/patches/CVE-2015-3247.patch
new file mode 100644
index 0000000..32b43ca
--- /dev/null
+++ b/debian/patches/CVE-2015-3247.patch
@@ -0,0 +1,117 @@
+From 524eef10c6c6c2f3f30be28c56b8f96adc7901f0 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 9 Jun 2015 08:50:46 +0100
+Subject: [PATCH] Avoid race conditions reading monitor configs from guest
+
+For security reasons do not assume guest do not change structures it
+pass to Qemu.
+Guest could change count field while Qemu is copying QXLMonitorsConfig
+structure leading to heap corruption.
+This patch avoid it reading count only once.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_worker.c | 46 ++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 32 insertions(+), 14 deletions(-)
+
+Index: spice/server/red_worker.c
+===================================================================
+--- spice.orig/server/red_worker.c
++++ spice/server/red_worker.c
+@@ -11051,7 +11051,8 @@ static inline void red_monitors_config_i
+ }
+ 
+ static void worker_update_monitors_config(RedWorker *worker,
+-                                          QXLMonitorsConfig *dev_monitors_config)
++                                          QXLMonitorsConfig *dev_monitors_config,
++                                          uint16_t count, uint16_t max_allowed)
+ {
+     int heads_size;
+     MonitorsConfig *monitors_config;
+@@ -11060,22 +11061,22 @@ static void worker_update_monitors_confi
+     monitors_config_decref(worker->monitors_config);
+ 
+     spice_debug("monitors config %d(%d)",
+-                dev_monitors_config->count,
+-                dev_monitors_config->max_allowed);
+-    for (i = 0; i < dev_monitors_config->count; i++) {
++                count,
++                max_allowed);
++    for (i = 0; i < count; i++) {
+         spice_debug("+%d+%d %dx%d",
+                     dev_monitors_config->heads[i].x,
+                     dev_monitors_config->heads[i].y,
+                     dev_monitors_config->heads[i].width,
+                     dev_monitors_config->heads[i].height);
+     }
+-    heads_size = dev_monitors_config->count * sizeof(QXLHead);
++    heads_size = count * sizeof(QXLHead);
+     worker->monitors_config = monitors_config =
+         spice_malloc(sizeof(*monitors_config) + heads_size);
+     monitors_config->refs = 1;
+     monitors_config->worker = worker;
+-    monitors_config->count = dev_monitors_config->count;
+-    monitors_config->max_allowed = dev_monitors_config->max_allowed;
++    monitors_config->count = count;
++    monitors_config->max_allowed = max_allowed;
+     memcpy(monitors_config->heads, dev_monitors_config->heads, heads_size);
+ }
+ 
+@@ -11459,33 +11460,50 @@ void handle_dev_display_migrate(void *op
+     red_migrate_display(worker, rcc);
+ }
+ 
++static inline uint32_t qxl_monitors_config_size(uint32_t heads)
++{
++    return sizeof(QXLMonitorsConfig) + sizeof(QXLHead) * heads;
++}
++
+ static void handle_dev_monitors_config_async(void *opaque, void *payload)
+ {
+     RedWorkerMessageMonitorsConfigAsync *msg = payload;
+     RedWorker *worker = opaque;
+-    int min_size = sizeof(QXLMonitorsConfig) + sizeof(QXLHead);
+     int error;
++    uint16_t count, max_allowed;
+     QXLMonitorsConfig *dev_monitors_config =
+         (QXLMonitorsConfig*)get_virt(&worker->mem_slots, msg->monitors_config,
+-                                     min_size, msg->group_id, &error);
++                                     qxl_monitors_config_size(1),
++                                     msg->group_id, &error);
+ 
+     if (error) {
+         /* TODO: raise guest bug (requires added QXL interface) */
+         return;
+     }
+     worker->driver_cap_monitors_config = 1;
+-    if (dev_monitors_config->count == 0) {
++    count = dev_monitors_config->count;
++    max_allowed = dev_monitors_config->max_allowed;
++    if (count == 0) {
+         spice_warning("ignoring an empty monitors config message from driver");
+         return;
+     }
+-    if (dev_monitors_config->count > dev_monitors_config->max_allowed) {
++    if (count > max_allowed) {
+         spice_warning("ignoring malformed monitors_config from driver, "
+                       "count > max_allowed %d > %d",
+-                      dev_monitors_config->count,
+-                      dev_monitors_config->max_allowed);
++                      count,
++                      max_allowed);
++        return;
++    }
++    /* get pointer again to check virtual size */
++    dev_monitors_config =
++        (QXLMonitorsConfig*)get_virt(&worker->mem_slots, msg->monitors_config,
++                                     qxl_monitors_config_size(count),
++                                     msg->group_id, &error);
++    if (error) {
++        /* TODO: raise guest bug (requires added QXL interface) */
+         return;
+     }
+-    worker_update_monitors_config(worker, dev_monitors_config);
++    worker_update_monitors_config(worker, dev_monitors_config, count, max_allowed);
+     red_worker_push_monitors_config(worker);
+ }
+ 
diff --git a/debian/patches/CVE-2015-3247.patch~ b/debian/patches/CVE-2015-3247.patch~
new file mode 100644
index 0000000..9c1014c
--- /dev/null
+++ b/debian/patches/CVE-2015-3247.patch~
@@ -0,0 +1,115 @@
+From 524eef10c6c6c2f3f30be28c56b8f96adc7901f0 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio at redhat.com>
+Date: Tue, 9 Jun 2015 08:50:46 +0100
+Subject: [PATCH] Avoid race conditions reading monitor configs from guest
+
+For security reasons do not assume guest do not change structures it
+pass to Qemu.
+Guest could change count field while Qemu is copying QXLMonitorsConfig
+structure leading to heap corruption.
+This patch avoid it reading count only once.
+
+Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
+---
+ server/red_worker.c | 46 ++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 32 insertions(+), 14 deletions(-)
+
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -11051,7 +11051,8 @@ static inline void red_monitors_config_i
+ }
+ 
+ static void worker_update_monitors_config(RedWorker *worker,
+-                                          QXLMonitorsConfig *dev_monitors_config)
++                                          QXLMonitorsConfig *dev_monitors_config,
++                                          uint16_t count, uint16_t max_allowed)
+ {
+     int heads_size;
+     MonitorsConfig *monitors_config;
+@@ -11060,22 +11061,22 @@ static void worker_update_monitors_confi
+     monitors_config_decref(worker->monitors_config);
+ 
+     spice_debug("monitors config %d(%d)",
+-                dev_monitors_config->count,
+-                dev_monitors_config->max_allowed);
+-    for (i = 0; i < dev_monitors_config->count; i++) {
++                count,
++                max_allowed);
++    for (i = 0; i < count; i++) {
+         spice_debug("+%d+%d %dx%d",
+                     dev_monitors_config->heads[i].x,
+                     dev_monitors_config->heads[i].y,
+                     dev_monitors_config->heads[i].width,
+                     dev_monitors_config->heads[i].height);
+     }
+-    heads_size = dev_monitors_config->count * sizeof(QXLHead);
++    heads_size = count * sizeof(QXLHead);
+     worker->monitors_config = monitors_config =
+         spice_malloc(sizeof(*monitors_config) + heads_size);
+     monitors_config->refs = 1;
+     monitors_config->worker = worker;
+-    monitors_config->count = dev_monitors_config->count;
+-    monitors_config->max_allowed = dev_monitors_config->max_allowed;
++    monitors_config->count = count;
++    monitors_config->max_allowed = max_allowed;
+     memcpy(monitors_config->heads, dev_monitors_config->heads, heads_size);
+ }
+ 
+@@ -11459,33 +11460,50 @@ void handle_dev_display_migrate(void *op
+     red_migrate_display(worker, rcc);
+ }
+ 
++static inline uint32_t qxl_monitors_config_size(uint32_t heads)
++{
++    return sizeof(QXLMonitorsConfig) + sizeof(QXLHead) * heads;
++}
++
+ static void handle_dev_monitors_config_async(void *opaque, void *payload)
+ {
+     RedWorkerMessageMonitorsConfigAsync *msg = payload;
+     RedWorker *worker = opaque;
+-    int min_size = sizeof(QXLMonitorsConfig) + sizeof(QXLHead);
+     int error;
++    uint16_t count, max_allowed;
+     QXLMonitorsConfig *dev_monitors_config =
+         (QXLMonitorsConfig*)get_virt(&worker->mem_slots, msg->monitors_config,
+-                                     min_size, msg->group_id, &error);
++                                     qxl_monitors_config_size(1),
++                                     msg->group_id, &error);
+ 
+     if (error) {
+         /* TODO: raise guest bug (requires added QXL interface) */
+         return;
+     }
+     worker->driver_cap_monitors_config = 1;
+-    if (dev_monitors_config->count == 0) {
++    count = dev_monitors_config->count;
++    max_allowed = dev_monitors_config->max_allowed;
++    if (count == 0) {
+         spice_warning("ignoring an empty monitors config message from driver");
+         return;
+     }
+-    if (dev_monitors_config->count > dev_monitors_config->max_allowed) {
++    if (count > max_allowed) {
+         spice_warning("ignoring malformed monitors_config from driver, "
+                       "count > max_allowed %d > %d",
+-                      dev_monitors_config->count,
+-                      dev_monitors_config->max_allowed);
++                      count,
++                      max_allowed);
++        return;
++    }
++    /* get pointer again to check virtual size */
++    dev_monitors_config =
++        (QXLMonitorsConfig*)get_virt(&worker->mem_slots, msg->monitors_config,
++                                     qxl_monitors_config_size(count),
++                                     msg->group_id, &error);
++    if (error) {
++        /* TODO: raise guest bug (requires added QXL interface) */
+         return;
+     }
+-    worker_update_monitors_config(worker, dev_monitors_config);
++    worker_update_monitors_config(worker, dev_monitors_config, count, max_allowed);
+     red_worker_push_monitors_config(worker);
+ }
+ 
diff --git a/debian/patches/fix-tests-warnings.patch b/debian/patches/fix-tests-warnings.patch
new file mode 100644
index 0000000..70a3651
--- /dev/null
+++ b/debian/patches/fix-tests-warnings.patch
@@ -0,0 +1,53 @@
+Date: Mon, 11 Feb 2013 08:49:58 -0600
+From: Serge Hallyn <serge.hallyn at ubuntu.com>
+Subject: [PATCH (v2)] Small cleanups to address compiler warnings
+Message-ID: <20130211144958.GA6481 at sergelap>
+Forwarded: yes
+
+Changelog: Feb 11: Address feedback by Marc-André:
+
+Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
+---
+ server/tests/basic_event_loop.c  | 4 ++--
+ server/tests/test_display_base.c | 8 +++++---
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+Index: spice/server/tests/basic_event_loop.c
+===================================================================
+--- spice.orig/server/tests/basic_event_loop.c
++++ spice/server/tests/basic_event_loop.c
+@@ -115,7 +115,7 @@ static void watch_remove(SpiceWatch *wat
+ 
+ static void channel_event(int event, SpiceChannelEventInfo *info)
+ {
+-    DPRINTF(0, "channel event con, type, id, event: %ld, %d, %d, %d",
++    DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d",
+             info->connection_id, info->type, info->id, event);
+ }
+ 
+@@ -215,7 +215,7 @@ void basic_event_loop_mainloop(void)
+         if ((next_timer = get_next_timer()) != NULL) {
+             calc_next_timeout(next_timer, &next_timer_timeout);
+             timeout = &next_timer_timeout;
+-            DPRINTF(2, "timeout of %zd.%06zd",
++            DPRINTF(2, "timeout of %ld.%06ld",
+                     timeout->tv_sec, timeout->tv_usec);
+         } else {
+             timeout = NULL;
+Index: spice/server/tests/test_display_base.c
+===================================================================
+--- spice.orig/server/tests/test_display_base.c
++++ spice/server/tests/test_display_base.c
+@@ -88,10 +88,11 @@ static void regression_test(void)
+     pid = fork();
+     if (pid == 0) {
+         char buf[PATH_MAX];
++        char *argp[] = {NULL};
+         char *envp[] = {buf, NULL};
+ 
+         snprintf(buf, sizeof(buf), "PATH=%s", getenv("PATH"));
+-        execve("regression_test.py", NULL, envp);
++        execve("regression_test.py", argp, envp);
+     } else if (pid > 0) {
+         return;
+     }
diff --git a/debian/patches/series b/debian/patches/series
index 247f05d..edcb062 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,22 @@
 allow-to-set-sasl-callbacks.patch
+fix-tests-warnings.patch
+CVE-2015-3247.patch
+0001-worker-validate-correctly-surfaces.patch
+0002-worker-avoid-double-free-or-double-create-of-surface.patch
+0003-Define-a-constant-to-limit-data-from-guest.patch
+0004-Fix-some-integer-overflow-causing-large-memory-alloc.patch
+0005-Check-properly-surface-to-be-created.patch
+0006-Fix-buffer-reading-overflow.patch
+0007-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
+0008-Fix-race-condition-on-red_get_clip_rects.patch
+0009-Fix-race-in-red_get_image.patch
+0010-Fix-race-condition-in-red_get_string.patch
+0011-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
+0012-Fix-race-condition-in-red_get_data_chunks_ptr.patch
+0013-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
+0014-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
+0015-Fix-some-possible-overflows-in-red_get_string-for-32.patch
+0016-Make-sure-we-can-read-QXLPathSeg-structures.patch
+0017-Avoid-race-condition-copying-segments-in-red_get_pat.patch
+0018-Prevent-data_size-to-be-set-independently-from-data.patch
+0019-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
-- 
2.1.4




More information about the pve-devel mailing list