diff --git a/SOURCES/0038-Add-const-to-test_capability-first-argument.patch b/SOURCES/0038-Add-const-to-test_capability-first-argument.patch
new file mode 100644
index 0000000..7fd9526
--- /dev/null
+++ b/SOURCES/0038-Add-const-to-test_capability-first-argument.patch
@@ -0,0 +1,40 @@
+From 17fd07ff2fd287fff6cc866a308097e75cb968f5 Mon Sep 17 00:00:00 2001
+From: Christophe Fergeau <cfergeau@redhat.com>
+Date: Wed, 19 Mar 2014 18:17:32 +0100
+Subject: [PATCH 1/3] Add const to test_capability first argument
+
+We don't modify the capabilities content, so it can be marked as const.
+---
+ server/red_channel.c | 2 +-
+ server/red_channel.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/server/red_channel.c b/server/red_channel.c
+index 5df8f14..449e628 100644
+--- a/server/red_channel.c
++++ b/server/red_channel.c
+@@ -1159,7 +1159,7 @@ void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs)
+     }
+ }
+ 
+-int test_capabilty(uint32_t *caps, int num_caps, uint32_t cap)
++int test_capabilty(const uint32_t *caps, int num_caps, uint32_t cap)
+ {
+     uint32_t index = cap / 32;
+     if (num_caps < index + 1) {
+diff --git a/server/red_channel.h b/server/red_channel.h
+index 9e54dce..58109d5 100644
+--- a/server/red_channel.h
++++ b/server/red_channel.h
+@@ -223,7 +223,7 @@ typedef struct RedChannelCapabilities {
+     uint32_t *caps;
+ } RedChannelCapabilities;
+ 
+-int test_capabilty(uint32_t *caps, int num_caps, uint32_t cap);
++int test_capabilty(const uint32_t *caps, int num_caps, uint32_t cap);
+ 
+ typedef struct RedChannelClientLatencyMonitor {
+     int state;
+-- 
+2.4.4
+
diff --git a/SOURCES/0038-Avoid-race-conditions-reading-monitor-configs-from-g.patch b/SOURCES/0038-Avoid-race-conditions-reading-monitor-configs-from-g.patch
deleted file mode 100644
index c909575..0000000
--- a/SOURCES/0038-Avoid-race-conditions-reading-monitor-configs-from-g.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-From 524eef10c6c6c2f3f30be28c56b8f96adc7901f0 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@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@redhat.com>
----
- server/red_worker.c | 46 ++++++++++++++++++++++++++++++++--------------
- 1 file changed, 32 insertions(+), 14 deletions(-)
-
-diff --git a/server/red_worker.c b/server/red_worker.c
-index 9e6a6ad..955cac2 100644
---- a/server/red_worker.c
-+++ b/server/red_worker.c
-@@ -11270,7 +11270,8 @@ static inline void red_monitors_config_item_add(DisplayChannelClient *dcc)
- }
- 
- 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;
-@@ -11279,22 +11280,22 @@ static void worker_update_monitors_config(RedWorker *worker,
-     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);
- }
- 
-@@ -11678,33 +11679,50 @@ void handle_dev_display_migrate(void *opaque, void *payload)
-     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;
-     }
--    worker_update_monitors_config(worker, dev_monitors_config);
-+    /* 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, count, max_allowed);
-     red_worker_push_monitors_config(worker);
- }
- 
diff --git a/SOURCES/0039-Introduce-red_link_info_test_capability.patch b/SOURCES/0039-Introduce-red_link_info_test_capability.patch
new file mode 100644
index 0000000..8b17861
--- /dev/null
+++ b/SOURCES/0039-Introduce-red_link_info_test_capability.patch
@@ -0,0 +1,60 @@
+From 0b0ca2c972041b785145c558dfd0e8372869f696 Mon Sep 17 00:00:00 2001
+From: Christophe Fergeau <cfergeau@redhat.com>
+Date: Wed, 5 Mar 2014 11:59:37 +0100
+Subject: [PATCH 2/3] Introduce red_link_info_test_capability()
+
+This just hides a bit of pointer arithmetic away from reds_send_link_ack.
+This helper will be used in the next commits.
+---
+ server/reds.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/server/reds.c b/server/reds.c
+index ccba67c..c1edf67 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -1446,6 +1446,22 @@ static void reds_channel_init_auth_caps(RedLinkInfo *link, RedChannel *channel)
+     red_channel_set_common_cap(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+ }
+ 
++
++static const uint32_t *red_link_info_get_caps(const RedLinkInfo *link)
++{
++    const uint8_t *caps_start = (const uint8_t *)link->link_mess;
++
++    return (const uint32_t *)(caps_start + link->link_mess->caps_offset);
++}
++
++static bool red_link_info_test_capability(const RedLinkInfo *link, uint32_t cap)
++{
++    const uint32_t *caps = red_link_info_get_caps(link);
++
++    return test_capabilty(caps, link->link_mess->num_common_caps, cap);
++}
++
++
+ static int reds_send_link_ack(RedLinkInfo *link)
+ {
+     SpiceLinkHeader header;
+@@ -2701,7 +2717,6 @@ static void reds_handle_read_link_done(void *opaque)
+     SpiceLinkMess *link_mess = link->link_mess;
+     AsyncRead *obj = &link->asyc_read;
+     uint32_t num_caps = link_mess->num_common_caps + link_mess->num_channel_caps;
+-    uint32_t *caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset);
+     int auth_selection;
+ 
+     if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset >
+@@ -2712,8 +2727,8 @@ static void reds_handle_read_link_done(void *opaque)
+         return;
+     }
+ 
+-    auth_selection = test_capabilty(caps, link_mess->num_common_caps,
+-                                    SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
++    auth_selection = red_link_info_test_capability(link,
++                                                   SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+ 
+     if (!reds_security_check(link)) {
+         if (link->stream->ssl) {
+-- 
+2.4.4
+
diff --git a/SOURCES/0039-worker-validate-correctly-surfaces.patch b/SOURCES/0039-worker-validate-correctly-surfaces.patch
deleted file mode 100644
index f7a89d8..0000000
--- a/SOURCES/0039-worker-validate-correctly-surfaces.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-From bea51d967731a2be7741fcbeef799b9fd925343a Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Wed, 9 Sep 2015 12:42:09 +0100
-Subject: [PATCH 1/2] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_worker.c | 33 ++++++++++++++++++---------------
- 1 file changed, 18 insertions(+), 15 deletions(-)
-
-diff --git a/server/red_worker.c b/server/red_worker.c
-index 93e3398..c62dbcb 100644
---- a/server/red_worker.c
-+++ b/server/red_worker.c
-@@ -1054,6 +1054,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
-@@ -1267,11 +1268,6 @@ static inline int is_primary_surface(RedWorker *worker, uint32_t surface_id)
-     return FALSE;
- }
- 
--static inline void __validate_surface(RedWorker *worker, uint32_t surface_id)
--{
--    spice_warn_if(surface_id >= worker->n_surfaces);
--}
--
- static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
- {
-         DrawContext *context;
-@@ -1280,7 +1276,7 @@ static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
-         /* surface_id must be validated before calling into
-          * validate_drawable_bbox
-          */
--        __validate_surface(worker, surface_id);
-+        VALIDATE_SURFACE_RETVAL(worker, surface_id, FALSE);
-         context = &worker->surfaces[surface_id].context;
- 
-         if (drawable->bbox.top < 0)
-@@ -1301,7 +1297,10 @@ static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
- 
- 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);
-@@ -4304,12 +4303,14 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uin
- 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];
- 
-@@ -4345,6 +4346,7 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
-     default:
-             spice_error("unknown surface command");
-     };
-+exit:
-     red_put_surface_cmd(surface);
-     free(surface);
- }
-@@ -11091,7 +11093,7 @@ void handle_dev_update(void *opaque, void *payload)
- {
-     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;
-@@ -11099,17 +11101,16 @@ void handle_dev_update(void *opaque, void *payload)
-     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,
-@@ -11148,6 +11149,7 @@ void handle_dev_del_memslot(void *opaque, void *payload)
-  * 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;
-     }
-@@ -11412,6 +11414,7 @@ void handle_dev_create_primary_surface(void *opaque, void *payload)
- 
- 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);
--- 
-2.4.3
-
diff --git a/SOURCES/0040-Don-t-set-SpiceLinkReply-pub_key-if-client-advertise.patch b/SOURCES/0040-Don-t-set-SpiceLinkReply-pub_key-if-client-advertise.patch
new file mode 100644
index 0000000..47993b3
--- /dev/null
+++ b/SOURCES/0040-Don-t-set-SpiceLinkReply-pub_key-if-client-advertise.patch
@@ -0,0 +1,111 @@
+From 3a3ec08f25e2b53e9de256fcb3a4f951c4b1e871 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
+Date: Thu, 9 Jul 2015 01:04:31 +0200
+Subject: [PATCH 3/3] Don't set SpiceLinkReply::pub_key if client advertises
+ SASL cap
+
+If the client advertises the SASL cap, it means it guarantees it will be
+able to use SASL if the server supports, and that it does not need a valid
+SpiceLinkReply::pub_key field when using SASL.
+
+When the client cap is set, we thus don't need to create a RSA public key
+if SASL is enabled server side.
+
+The reason for needing client guarantees about not looking at the pub_key
+field is that its presence and size is hardcoded in the protocol, but in
+some hardened setups (using fips mode), generating a RSA 1024 bit key as
+expected is forbidden and fails. With this new capability, the server
+knows the client will be able to handle SASL if needed, and can skip
+the generation of the key altogether. This means that on the setups
+described above, SASL authentication has to be used.
+---
+ server/reds.c | 56 +++++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 39 insertions(+), 17 deletions(-)
+
+diff --git a/server/reds.c b/server/reds.c
+index c1edf67..9521416 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -1469,7 +1469,7 @@ static int reds_send_link_ack(RedLinkInfo *link)
+     RedChannel *channel;
+     RedChannelCapabilities *channel_caps;
+     BUF_MEM *bmBuf;
+-    BIO *bio;
++    BIO *bio = NULL;
+     int ret = FALSE;
+ 
+     header.magic = SPICE_MAGIC;
+@@ -1494,24 +1494,45 @@ static int reds_send_link_ack(RedLinkInfo *link)
+     ack.num_channel_caps = channel_caps->num_caps;
+     header.size += (ack.num_common_caps + ack.num_channel_caps) * sizeof(uint32_t);
+     ack.caps_offset = sizeof(SpiceLinkReply);
++    if (!sasl_enabled
++        || !red_link_info_test_capability(link, SPICE_COMMON_CAP_AUTH_SASL)) {
++        if (!(link->tiTicketing.rsa = RSA_new())) {
++            spice_warning("RSA new failed");
++            return FALSE;
++        }
+ 
+-    if (!(link->tiTicketing.rsa = RSA_new())) {
+-        spice_warning("RSA nes failed");
+-        return FALSE;
+-    }
+-
+-    if (!(bio = BIO_new(BIO_s_mem()))) {
+-        spice_warning("BIO new failed");
+-        return FALSE;
+-    }
++        if (!(bio = BIO_new(BIO_s_mem()))) {
++            spice_warning("BIO new failed");
++            return FALSE;
++        }
+ 
+-    RSA_generate_key_ex(link->tiTicketing.rsa, SPICE_TICKET_KEY_PAIR_LENGTH, link->tiTicketing.bn,
+-                        NULL);
+-    link->tiTicketing.rsa_size = RSA_size(link->tiTicketing.rsa);
++        if (RSA_generate_key_ex(link->tiTicketing.rsa,
++                                SPICE_TICKET_KEY_PAIR_LENGTH,
++                                link->tiTicketing.bn,
++                                NULL) != 1) {
++            spice_warning("Failed to generate %d bits RSA key: %s",
++                          SPICE_TICKET_KEY_PAIR_LENGTH,
++                          ERR_error_string(ERR_get_error(), NULL));
++           goto end;
++        }
++        link->tiTicketing.rsa_size = RSA_size(link->tiTicketing.rsa);
+ 
+-    i2d_RSA_PUBKEY_bio(bio, link->tiTicketing.rsa);
+-    BIO_get_mem_ptr(bio, &bmBuf);
+-    memcpy(ack.pub_key, bmBuf->data, sizeof(ack.pub_key));
++        i2d_RSA_PUBKEY_bio(bio, link->tiTicketing.rsa);
++        BIO_get_mem_ptr(bio, &bmBuf);
++        memcpy(ack.pub_key, bmBuf->data, sizeof(ack.pub_key));
++    } else {
++        /* if the client sets the AUTH_SASL cap, it indicates that it
++         * supports SASL, and will use it if the server supports SASL as
++         * well. Moreover, a client setting the AUTH_SASL cap also
++         * indicates that it will not try using the RSA-related content
++         * in the SpiceLinkReply message, so we don't need to initialize
++         * it. Reason to avoid this is to fix auth in fips mode where
++         * the generation of a 1024 bit RSA key as we are trying to do
++         * will fail.
++         */
++         spice_warning("not initialising RSA key");
++         memset(ack.pub_key, '\0', sizeof(ack.pub_key));
++    }
+ 
+     if (!sync_write(link->stream, &header, sizeof(header)))
+         goto end;
+@@ -1525,7 +1546,8 @@ static int reds_send_link_ack(RedLinkInfo *link)
+     ret = TRUE;
+ 
+ end:
+-    BIO_free(bio);
++    if (bio != NULL)
++        BIO_free(bio);
+     return ret;
+ }
+ 
+-- 
+2.4.4
+
diff --git a/SOURCES/0040-worker-avoid-double-free-or-double-create-of-surface.patch b/SOURCES/0040-worker-avoid-double-free-or-double-create-of-surface.patch
deleted file mode 100644
index 2ef2398..0000000
--- a/SOURCES/0040-worker-avoid-double-free-or-double-create-of-surface.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 269e9d112639ab6c54645de217c46ef75617d780 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Wed, 9 Sep 2015 12:45:06 +0100
-Subject: [PATCH 2/2] 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@redhat.com>
----
- server/red_worker.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/server/red_worker.c b/server/red_worker.c
-index c62dbcb..a7eaab9 100644
---- a/server/red_worker.c
-+++ b/server/red_worker.c
-@@ -4320,6 +4320,10 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
-         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));
-@@ -4333,7 +4337,10 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
-         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.
--- 
-2.4.3
-
diff --git a/SOURCES/0041-Define-a-constant-to-limit-data-from-guest.patch b/SOURCES/0041-Define-a-constant-to-limit-data-from-guest.patch
deleted file mode 100644
index d569778..0000000
--- a/SOURCES/0041-Define-a-constant-to-limit-data-from-guest.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 247209c1f1c6a41d9fe0532ae17f19ae1cdcc2f7 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 11:58:11 +0100
-Subject: [PATCH 41/57] 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@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 6c0b065..4449f2c 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.4.3
-
diff --git a/SOURCES/0041-server-don-t-assert-on-invalid-client-message.patch b/SOURCES/0041-server-don-t-assert-on-invalid-client-message.patch
new file mode 100644
index 0000000..a3750ca
--- /dev/null
+++ b/SOURCES/0041-server-don-t-assert-on-invalid-client-message.patch
@@ -0,0 +1,33 @@
+From cf19a886b8ce41ce7c5159a2898f9587318a32ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
+Date: Wed, 25 Jun 2014 14:36:03 +0200
+Subject: [PATCH] server: don't assert on invalid client message
+
+Some users have been reaching this error:
+snd_receive: ASSERT n failed
+
+A misbehaving client could easily hit that condition by sending too big
+messages. Instead of assert(), replace with a warning. When a message
+too big to fit is received, it will simply disconnect the channel.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=962187
+---
+ server/snd_worker.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/server/snd_worker.c b/server/snd_worker.c
+index ebddfcd..c451031 100644
+--- a/server/snd_worker.c
++++ b/server/snd_worker.c
+@@ -421,7 +421,7 @@ static void snd_receive(void* data)
+     for (;;) {
+         ssize_t n;
+         n = channel->recive_data.end - channel->recive_data.now;
+-        spice_assert(n);
++        spice_warn_if(n <= 0);
+         n = reds_stream_read(channel->stream, channel->recive_data.now, n);
+         if (n <= 0) {
+             if (n == 0) {
+-- 
+2.4.4
+
diff --git a/SOURCES/0042-Don-t-truncate-large-now-values-in-_spice_timer_set.patch b/SOURCES/0042-Don-t-truncate-large-now-values-in-_spice_timer_set.patch
new file mode 100644
index 0000000..792da4f
--- /dev/null
+++ b/SOURCES/0042-Don-t-truncate-large-now-values-in-_spice_timer_set.patch
@@ -0,0 +1,80 @@
+From d6f73e30020e0e2cbe6ee48d5f1bf38e0587ba83 Mon Sep 17 00:00:00 2001
+From: David Gibson <dgibson@redhat.com>
+Date: Mon, 10 Mar 2014 11:55:47 +0100
+Subject: [PATCH] Don't truncate large 'now' values in _spice_timer_set
+
+static void _spice_timer_set(SpiceTimer *timer, uint32_t ms, uint32_t now)
+
+The _spice_timer_set() function takes a 32-bit integer for the "now" value.
+The now value passed in however, can exceed 2^32 (it's in ms and derived
+from CLOCK_MONOTONIC, which will wrap around a 32-bit integer in around 46
+days).
+
+If the now value passed in exceeds 2^32, this will mean timers are inserted
+into the active list with expiry values before the current time, they will
+immediately trigger, and (if they don't make themselves inactive) be
+reinserted still before the current time.
+
+This leads to an infinite loop in spice_timer_queue_cb().
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1072700
+---
+ server/spice_timer_queue.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/server/spice_timer_queue.c b/server/spice_timer_queue.c
+index 8f6e9c8..71de84a 100644
+--- a/server/spice_timer_queue.c
++++ b/server/spice_timer_queue.c
+@@ -147,7 +147,7 @@ SpiceTimer *spice_timer_queue_add(SpiceTimerFunc func, void *opaque)
+     return timer;
+ }
+ 
+-static void _spice_timer_set(SpiceTimer *timer, uint32_t ms, uint32_t now)
++static void _spice_timer_set(SpiceTimer *timer, uint32_t ms, uint64_t now)
+ {
+     RingItem *next_item;
+     SpiceTimerQueue *queue;
+@@ -183,7 +183,8 @@ void spice_timer_set(SpiceTimer *timer, uint32_t ms)
+     spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
+ 
+     clock_gettime(CLOCK_MONOTONIC, &now);
+-    _spice_timer_set(timer, ms, now.tv_sec * 1000 + (now.tv_nsec / 1000 / 1000));
++    _spice_timer_set(timer, ms,
++                     (uint64_t)now.tv_sec * 1000 + (now.tv_nsec / 1000 / 1000));
+ }
+ 
+ void spice_timer_cancel(SpiceTimer *timer)
+@@ -217,7 +218,7 @@ void spice_timer_remove(SpiceTimer *timer)
+ unsigned int spice_timer_queue_get_timeout_ms(void)
+ {
+     struct timespec now;
+-    int now_ms;
++    int64_t now_ms;
+     RingItem *head;
+     SpiceTimer *head_timer;
+     SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
+@@ -232,9 +233,9 @@ unsigned int spice_timer_queue_get_timeout_ms(void)
+     head_timer = SPICE_CONTAINEROF(head, SpiceTimer, active_link);
+ 
+     clock_gettime(CLOCK_MONOTONIC, &now);
+-    now_ms = (now.tv_sec * 1000) - (now.tv_nsec / 1000 / 1000);
++    now_ms = ((int64_t)now.tv_sec * 1000) - (now.tv_nsec / 1000 / 1000);
+ 
+-    return MAX(0, ((int)head_timer->expiry_time - now_ms));
++    return MAX(0, ((int64_t)head_timer->expiry_time - now_ms));
+ }
+ 
+ 
+@@ -252,7 +253,7 @@ void spice_timer_queue_cb(void)
+     }
+ 
+     clock_gettime(CLOCK_MONOTONIC, &now);
+-    now_ms = (now.tv_sec * 1000) + (now.tv_nsec / 1000 / 1000);
++    now_ms = ((uint64_t)now.tv_sec * 1000) + (now.tv_nsec / 1000 / 1000);
+ 
+     while ((head = ring_get_head(&queue->active_timers))) {
+         SpiceTimer *timer = SPICE_CONTAINEROF(head, SpiceTimer, active_link);
+-- 
+2.4.4
+
diff --git a/SOURCES/0042-Fix-some-integer-overflow-causing-large-memory-alloc.patch b/SOURCES/0042-Fix-some-integer-overflow-causing-large-memory-alloc.patch
deleted file mode 100644
index ff5e6af..0000000
--- a/SOURCES/0042-Fix-some-integer-overflow-causing-large-memory-alloc.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From b9ee3c381ef823b6a4f246e0df3112efdd349b6a Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Thu, 17 Sep 2015 15:00:22 +0100
-Subject: [PATCH 42/57] 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@redhat.com>
----
- server/red_parse_qxl.c | 15 +++++++++++----
- 1 file changed, 11 insertions(+), 4 deletions(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index 4449f2c..ceb2759 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -384,7 +384,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
-     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(RedMemSlotInfo *slots, int group_id,
-             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 * 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,
-@@ -1220,7 +1223,7 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
-                         RedSurfaceCmd *red, QXLPHYSICAL addr)
- {
-     QXLSurfaceCmd *qxl;
--    size_t size;
-+    uint64_t size;
-     int error;
- 
-     qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
-@@ -1240,7 +1243,11 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
-         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) {
--- 
-2.4.3
-
diff --git a/SOURCES/0043-Avoid-race-conditions-reading-monitor-configs-from-g.patch b/SOURCES/0043-Avoid-race-conditions-reading-monitor-configs-from-g.patch
new file mode 100644
index 0000000..c26de66
--- /dev/null
+++ b/SOURCES/0043-Avoid-race-conditions-reading-monitor-configs-from-g.patch
@@ -0,0 +1,120 @@
+From 4249d114abe6ace0553b6cfd1464e220d1e5acb1 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@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@redhat.com>
+---
+ server/red_worker.c | 46 ++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 32 insertions(+), 14 deletions(-)
+
+diff --git a/server/red_worker.c b/server/red_worker.c
+index 9e6a6ad..955cac2 100644
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -11270,7 +11270,8 @@ static inline void red_monitors_config_item_add(DisplayChannelClient *dcc)
+ }
+ 
+ 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;
+@@ -11279,22 +11280,22 @@ static void worker_update_monitors_config(RedWorker *worker,
+     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);
+ }
+ 
+@@ -11678,33 +11679,50 @@ void handle_dev_display_migrate(void *opaque, void *payload)
+     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);
+ }
+ 
+-- 
+2.4.4
+
diff --git a/SOURCES/0043-Check-properly-surface-to-be-created.patch b/SOURCES/0043-Check-properly-surface-to-be-created.patch
deleted file mode 100644
index 05c24d9..0000000
--- a/SOURCES/0043-Check-properly-surface-to-be-created.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From b15d9c6d94bf426d61aaa4631ed55271c0d12b14 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 16:02:59 +0100
-Subject: [PATCH 43/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_parse_qxl.c | 35 ++++++++++++++++++++++++++++++++++-
- 1 file changed, 34 insertions(+), 1 deletion(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index ceb2759..a7ca71d 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -1219,12 +1219,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);
-@@ -1243,9 +1261,24 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
-         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 =
--- 
-2.4.3
-
diff --git a/SOURCES/0044-Fix-buffer-reading-overflow.patch b/SOURCES/0044-Fix-buffer-reading-overflow.patch
deleted file mode 100644
index bc0240d..0000000
--- a/SOURCES/0044-Fix-buffer-reading-overflow.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 18087073df84885642d9b0b1efd0e86e18409bbe Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 10:00:37 +0100
-Subject: [PATCH 44/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 a7ca71d..01cba0f 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_error("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
--- 
-2.4.3
-
diff --git a/SOURCES/0044-Lock-the-pixmap-image-cache-for-the-entire-fill_bits.patch b/SOURCES/0044-Lock-the-pixmap-image-cache-for-the-entire-fill_bits.patch
new file mode 100644
index 0000000..bcc9e80
--- /dev/null
+++ b/SOURCES/0044-Lock-the-pixmap-image-cache-for-the-entire-fill_bits.patch
@@ -0,0 +1,223 @@
+From 6f7e2fca1030e38f3a82f09b30a4839923f17c66 Mon Sep 17 00:00:00 2001
+From: Sandy Stutsman <sstutsma@redhat.com>
+Date: Fri, 26 Jun 2015 11:59:13 -0400
+Subject: [PATCH] Lock the pixmap image cache for the entire fill_bits call
+
+Locking the individual calls that access the pixmap cache in fill_bits is
+not adequately thread safe.  Often a windows guest with multiple monitors
+will be sending the same image via different threads.  Both threads can
+be in fill_bits at the same time making changes to the cache for the same
+image.  This can result in images being deleted before all the client
+channels are finished with them or with the same image being send multiple
+times.  Here's what can happen with out the lock in fill_bits
+
+On the server in red_worker.c:fill_bits
+ Thread 1 calls pixmap_cache_hit for Image A and finds it isn't in cache
+ Thread 2 calls pixmap_cache_hit for Image A and finds it isn't in cache
+
+ Thread 1 adds Image 1 to pixmap_cache (1x)
+ Thread 2 adds Image 1 to pixmap_cache (2x)
+
+On the client
+ Channel 1 adds Image A to image_cache (1x)
+ Channel 2 replaces Image A in image_cache (1x)
+
+On server
+ Thread 1 sends Image A rendering commands
+ Thread N removes Image A from pixmap_cache (image remains - 1x)
+ Thread 2 sends Image A rendering commands
+
+On client
+ Channe1 renders from Image A
+ Channel N removes Image a from image_cache (image is completely removed)
+ Channel2 render command hangs waiting for Image A
+---
+ server/red_client_shared_cache.h | 24 ++++++++++++------------
+ server/red_worker.c              | 23 +++++++++++++++--------
+ 2 files changed, 27 insertions(+), 20 deletions(-)
+
+diff --git a/server/red_client_shared_cache.h b/server/red_client_shared_cache.h
+index 821ee18..7feb28e 100644
+--- a/server/red_client_shared_cache.h
++++ b/server/red_client_shared_cache.h
+@@ -36,13 +36,12 @@
+ 
+ #define CHANNEL_FROM_RCC(rcc) SPICE_CONTAINEROF((rcc)->channel, CHANNEL, common.base);
+ 
+-static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, DisplayChannelClient *dcc)
++static int FUNC_NAME(unlocked_hit)(CACHE *cache, uint64_t id, int *lossy, DisplayChannelClient *dcc)
+ {
+     NewCacheItem *item;
+     uint64_t serial;
+ 
+     serial = red_channel_client_get_message_serial(&dcc->common.base);
+-    pthread_mutex_lock(&cache->lock);
+     item = cache->hash_table[CACHE_HASH_KEY(id)];
+ 
+     while (item) {
+@@ -57,15 +56,22 @@ static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, DisplayChannelC
+         }
+         item = item->next;
+     }
+-    pthread_mutex_unlock(&cache->lock);
+ 
+     return !!item;
+ }
+ 
+-static int FUNC_NAME(set_lossy)(CACHE *cache, uint64_t id, int lossy)
++static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, DisplayChannelClient *dcc)
+ {
+-    NewCacheItem *item;
++    int hit;
+     pthread_mutex_lock(&cache->lock);
++    hit = FUNC_NAME(unlocked_hit)(cache,id,lossy, dcc);
++    pthread_mutex_unlock(&cache->lock);
++    return hit;
++}
++
++static int FUNC_NAME(unlocked_set_lossy)(CACHE *cache, uint64_t id, int lossy)
++{
++    NewCacheItem *item;
+ 
+     item = cache->hash_table[CACHE_HASH_KEY(id)];
+ 
+@@ -76,11 +82,10 @@ static int FUNC_NAME(set_lossy)(CACHE *cache, uint64_t id, int lossy)
+         }
+         item = item->next;
+     }
+-    pthread_mutex_unlock(&cache->lock);
+     return !!item;
+ }
+ 
+-static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, DisplayChannelClient *dcc)
++static int FUNC_NAME(unlocked_add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, DisplayChannelClient *dcc)
+ {
+     NewCacheItem *item;
+     uint64_t serial;
+@@ -91,15 +96,12 @@ static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, D
+     item = spice_new(NewCacheItem, 1);
+     serial = red_channel_client_get_message_serial(&dcc->common.base);
+ 
+-    pthread_mutex_lock(&cache->lock);
+-
+     if (cache->generation != dcc->CACH_GENERATION) {
+         if (!dcc->pending_pixmaps_sync) {
+             red_channel_client_pipe_add_type(
+                 &dcc->common.base, PIPE_ITEM_TYPE_PIXMAP_SYNC);
+             dcc->pending_pixmaps_sync = TRUE;
+         }
+-        pthread_mutex_unlock(&cache->lock);
+         free(item);
+         return FALSE;
+     }
+@@ -112,7 +114,6 @@ static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, D
+         if (!(tail = (NewCacheItem *)ring_get_tail(&cache->lru)) ||
+                                                    tail->sync[dcc->common.id] == serial) {
+             cache->available += size;
+-            pthread_mutex_unlock(&cache->lock);
+             free(item);
+             return FALSE;
+         }
+@@ -144,7 +145,6 @@ static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, D
+     memset(item->sync, 0, sizeof(item->sync));
+     item->sync[dcc->common.id] = serial;
+     cache->sync[dcc->common.id] = serial;
+-    pthread_mutex_unlock(&cache->lock);
+     return TRUE;
+ }
+ 
+diff --git a/server/red_worker.c b/server/red_worker.c
+index 955cac2..93e3398 100644
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -6750,9 +6750,9 @@ static inline void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
+     if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
+         spice_assert(image->descriptor.width * image->descriptor.height > 0);
+         if (!(io_image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME)) {
+-            if (pixmap_cache_add(dcc->pixmap_cache, image->descriptor.id,
+-                                 image->descriptor.width * image->descriptor.height, is_lossy,
+-                                 dcc)) {
++            if (pixmap_cache_unlocked_add(dcc->pixmap_cache, image->descriptor.id,
++                                          image->descriptor.width * image->descriptor.height, is_lossy,
++                                          dcc)) {
+                 io_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME;
+                 dcc->send_data.pixmap_cache_items[dcc->send_data.num_pixmap_cache_items++] =
+                                                                                image->descriptor.id;
+@@ -6797,11 +6797,12 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+     if (simage->descriptor.flags & SPICE_IMAGE_FLAGS_HIGH_BITS_SET) {
+         image.descriptor.flags = SPICE_IMAGE_FLAGS_HIGH_BITS_SET;
+     }
++    pthread_mutex_lock(&dcc->pixmap_cache->lock);
+ 
+     if ((simage->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
+         int lossy_cache_item;
+-        if (pixmap_cache_hit(dcc->pixmap_cache, image.descriptor.id,
+-                             &lossy_cache_item, dcc)) {
++        if (pixmap_cache_unlocked_hit(dcc->pixmap_cache, image.descriptor.id,
++                                      &lossy_cache_item, dcc)) {
+             dcc->send_data.pixmap_cache_items[dcc->send_data.num_pixmap_cache_items++] =
+                                                                                image.descriptor.id;
+             if (can_lossy || !lossy_cache_item) {
+@@ -6818,10 +6819,11 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+                 spice_assert(bitmap_palette_out == NULL);
+                 spice_assert(lzplt_palette_out == NULL);
+                 stat_inc_counter(display_channel->cache_hits_counter, 1);
++                pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+                 return FILL_BITS_TYPE_CACHE;
+             } else {
+-                pixmap_cache_set_lossy(dcc->pixmap_cache, simage->descriptor.id,
+-                                       FALSE);
++                pixmap_cache_unlocked_set_lossy(dcc->pixmap_cache, simage->descriptor.id,
++                                                FALSE);
+                 image.descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME;
+             }
+         }
+@@ -6835,6 +6837,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+         surface_id = simage->u.surface.surface_id;
+         if (!validate_surface(worker, surface_id)) {
+             rendering_incorrect("SPICE_IMAGE_TYPE_SURFACE");
++            pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+             return FILL_BITS_TYPE_SURFACE;
+         }
+ 
+@@ -6849,6 +6852,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+                              &bitmap_palette_out, &lzplt_palette_out);
+         spice_assert(bitmap_palette_out == NULL);
+         spice_assert(lzplt_palette_out == NULL);
++        pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+         return FILL_BITS_TYPE_SURFACE;
+     }
+     case SPICE_IMAGE_TYPE_BITMAP: {
+@@ -6879,6 +6883,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+             }
+ 
+             spice_marshaller_add_ref_chunks(m, bitmap->data);
++            pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+             return FILL_BITS_TYPE_BITMAP;
+         } else {
+             red_display_add_image_to_pixmap_cache(rcc, simage, &image,
+@@ -6896,6 +6901,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+             }
+ 
+             spice_assert(!comp_send_data.is_lossy || can_lossy);
++            pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+             return (comp_send_data.is_lossy ? FILL_BITS_TYPE_COMPRESS_LOSSY :
+                                               FILL_BITS_TYPE_COMPRESS_LOSSLESS);
+         }
+@@ -6909,11 +6915,12 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
+         spice_assert(bitmap_palette_out == NULL);
+         spice_assert(lzplt_palette_out == NULL);
+         spice_marshaller_add_ref_chunks(m, image.u.quic.data);
++        pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+         return FILL_BITS_TYPE_COMPRESS_LOSSLESS;
+     default:
+         spice_error("invalid image type %u", image.descriptor.type);
+     }
+-
++    pthread_mutex_unlock(&dcc->pixmap_cache->lock);
+     return 0;
+ }
+ 
+-- 
+2.4.4
+
diff --git a/SOURCES/0045-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch b/SOURCES/0045-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
deleted file mode 100644
index 822ab6d..0000000
--- a/SOURCES/0045-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 7baa8c39757b46a834e20198e4b18e9f1752e20e Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 13:09:35 +0100
-Subject: [PATCH 45/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_parse_qxl.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index 01cba0f..3385f52 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,8 +371,8 @@ static int bitmap_consistent(SpiceBitmap *bitmap)
- 
-     bpp = MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[bitmap->format];
- 
--    if (bitmap->stride < ((bitmap->x * bpp + 7) / 8)) {
--        spice_error("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
-+    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),
-                     bitmap->format);
--- 
-2.4.3
-
diff --git a/SOURCES/0045-reds-Assure-we-don-t-have-stale-statistic-files-befo.patch b/SOURCES/0045-reds-Assure-we-don-t-have-stale-statistic-files-befo.patch
new file mode 100644
index 0000000..951a92e
--- /dev/null
+++ b/SOURCES/0045-reds-Assure-we-don-t-have-stale-statistic-files-befo.patch
@@ -0,0 +1,37 @@
+From 40537f6a3e3389b8377b0ae790c62ea0da8aa6d8 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 15 Jul 2015 14:15:52 +0100
+Subject: [PATCH] reds: Assure we don't have stale statistic files before
+ trying to create a new one
+
+If a previous Qemu executable is not able to delete the statistic file
+on the next creation with same name (statitics file are based on pid
+numbers so if pid get reused for another Qemu process you get the same
+name) it fails as you can't open a file with 0444 permissions (these
+are the permission used to create these files).
+This patch assure there are no stale file trying to remove it before the
+creation of the new one. As file is based on pid and name used for spice
+you are not deleting another file.
+
+Fixes: rhbz#1177326
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+---
+ server/reds.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/server/reds.c b/server/reds.c
+index 57ef07a..c74894a 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -3291,6 +3291,7 @@ static int do_spice_init(SpiceCoreInterface *core_interface)
+     shm_name_len = strlen(SPICE_STAT_SHM_NAME) + 20;
+     reds->stat_shm_name = (char *)spice_malloc(shm_name_len);
+     snprintf(reds->stat_shm_name, shm_name_len, SPICE_STAT_SHM_NAME, getpid());
++    shm_unlink(reds->stat_shm_name);
+     if ((fd = shm_open(reds->stat_shm_name, O_CREAT | O_RDWR, 0444)) == -1) {
+         spice_error("statistics shm_open failed, %s", strerror(errno));
+     }
+-- 
+2.1.0
+
diff --git a/SOURCES/0046-Fix-race-condition-on-red_get_clip_rects.patch b/SOURCES/0046-Fix-race-condition-on-red_get_clip_rects.patch
deleted file mode 100644
index 279aeca..0000000
--- a/SOURCES/0046-Fix-race-condition-on-red_get_clip_rects.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 078a903d55f44aedd22b4fa8dd86e4b03b82c01c Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 10:01:51 +0100
-Subject: [PATCH 46/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 3385f52..affd3a2 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.4.3
-
diff --git a/SOURCES/0046-worker-validate-correctly-surfaces.patch b/SOURCES/0046-worker-validate-correctly-surfaces.patch
new file mode 100644
index 0000000..f7a89d8
--- /dev/null
+++ b/SOURCES/0046-worker-validate-correctly-surfaces.patch
@@ -0,0 +1,136 @@
+From bea51d967731a2be7741fcbeef799b9fd925343a Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 9 Sep 2015 12:42:09 +0100
+Subject: [PATCH 1/2] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_worker.c | 33 ++++++++++++++++++---------------
+ 1 file changed, 18 insertions(+), 15 deletions(-)
+
+diff --git a/server/red_worker.c b/server/red_worker.c
+index 93e3398..c62dbcb 100644
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -1054,6 +1054,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
+@@ -1267,11 +1268,6 @@ static inline int is_primary_surface(RedWorker *worker, uint32_t surface_id)
+     return FALSE;
+ }
+ 
+-static inline void __validate_surface(RedWorker *worker, uint32_t surface_id)
+-{
+-    spice_warn_if(surface_id >= worker->n_surfaces);
+-}
+-
+ static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
+ {
+         DrawContext *context;
+@@ -1280,7 +1276,7 @@ static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
+         /* surface_id must be validated before calling into
+          * validate_drawable_bbox
+          */
+-        __validate_surface(worker, surface_id);
++        VALIDATE_SURFACE_RETVAL(worker, surface_id, FALSE);
+         context = &worker->surfaces[surface_id].context;
+ 
+         if (drawable->bbox.top < 0)
+@@ -1301,7 +1297,10 @@ static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable)
+ 
+ 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);
+@@ -4304,12 +4303,14 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uin
+ 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];
+ 
+@@ -4345,6 +4346,7 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
+     default:
+             spice_error("unknown surface command");
+     };
++exit:
+     red_put_surface_cmd(surface);
+     free(surface);
+ }
+@@ -11091,7 +11093,7 @@ void handle_dev_update(void *opaque, void *payload)
+ {
+     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;
+@@ -11099,17 +11101,16 @@ void handle_dev_update(void *opaque, void *payload)
+     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,
+@@ -11148,6 +11149,7 @@ void handle_dev_del_memslot(void *opaque, void *payload)
+  * 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;
+     }
+@@ -11412,6 +11414,7 @@ void handle_dev_create_primary_surface(void *opaque, void *payload)
+ 
+ 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);
+-- 
+2.4.3
+
diff --git a/SOURCES/0047-Fix-race-in-red_get_image.patch b/SOURCES/0047-Fix-race-in-red_get_image.patch
deleted file mode 100644
index abaf5b3..0000000
--- a/SOURCES/0047-Fix-race-in-red_get_image.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From d2fc5cee16c10e53d81c6251e6929da54270a6f4 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 10:04:10 +0100
-Subject: [PATCH 47/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_parse_qxl.c | 18 ++++++++++--------
- 1 file changed, 10 insertions(+), 8 deletions(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index affd3a2..84ea526 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -397,6 +397,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
-     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(RedMemSlotInfo *slots, int group_id,
-     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(RedMemSlotInfo *slots, int group_id,
-         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;
-             }
--- 
-2.4.3
-
diff --git a/SOURCES/0047-worker-avoid-double-free-or-double-create-of-surface.patch b/SOURCES/0047-worker-avoid-double-free-or-double-create-of-surface.patch
new file mode 100644
index 0000000..2ef2398
--- /dev/null
+++ b/SOURCES/0047-worker-avoid-double-free-or-double-create-of-surface.patch
@@ -0,0 +1,46 @@
+From 269e9d112639ab6c54645de217c46ef75617d780 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 9 Sep 2015 12:45:06 +0100
+Subject: [PATCH 2/2] 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@redhat.com>
+---
+ server/red_worker.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/server/red_worker.c b/server/red_worker.c
+index c62dbcb..a7eaab9 100644
+--- a/server/red_worker.c
++++ b/server/red_worker.c
+@@ -4320,6 +4320,10 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
+         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));
+@@ -4333,7 +4337,10 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
+         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.
+-- 
+2.4.3
+
diff --git a/SOURCES/0048-Define-a-constant-to-limit-data-from-guest.patch b/SOURCES/0048-Define-a-constant-to-limit-data-from-guest.patch
new file mode 100644
index 0000000..d306102
--- /dev/null
+++ b/SOURCES/0048-Define-a-constant-to-limit-data-from-guest.patch
@@ -0,0 +1,42 @@
+From 2e1cac5508cd04815e0e624cdbc436857934f689 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 11:58:11 +0100
+Subject: [PATCH 48/64] 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@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 6c0b065..4449f2c 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.4.3
+
diff --git a/SOURCES/0048-Fix-race-condition-in-red_get_string.patch b/SOURCES/0048-Fix-race-condition-in-red_get_string.patch
deleted file mode 100644
index 8bc6bb5..0000000
--- a/SOURCES/0048-Fix-race-condition-in-red_get_string.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 932e27e50032c1c7032be3616217a2ab0586fe78 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 10:05:20 +0100
-Subject: [PATCH 48/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_parse_qxl.c | 15 +++++++++------
- 1 file changed, 9 insertions(+), 6 deletions(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index 84ea526..2d4636e 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -809,6 +809,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-     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) {
-@@ -825,13 +826,15 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-     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);
-@@ -848,11 +851,11 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-         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);
--- 
-2.4.3
-
diff --git a/SOURCES/0049-Fix-integer-overflow-computing-glyph_size-in-red_get.patch b/SOURCES/0049-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
deleted file mode 100644
index 9bf8b82..0000000
--- a/SOURCES/0049-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From e28c08d63490a2fb6b8cc07bf968eb16243e9c63 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 10:13:24 +0100
-Subject: [PATCH 49/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 2d4636e..c4b82be 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -807,7 +807,9 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-     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;
- 
-@@ -846,7 +848,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-     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]);
-     }
-@@ -867,7 +869,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-         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]);
--- 
-2.4.3
-
diff --git a/SOURCES/0049-Fix-some-integer-overflow-causing-large-memory-alloc.patch b/SOURCES/0049-Fix-some-integer-overflow-causing-large-memory-alloc.patch
new file mode 100644
index 0000000..6b24d9e
--- /dev/null
+++ b/SOURCES/0049-Fix-some-integer-overflow-causing-large-memory-alloc.patch
@@ -0,0 +1,69 @@
+From c0860a1bce777a2b54a31a01d09a71e80657b5ff Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Thu, 17 Sep 2015 15:00:22 +0100
+Subject: [PATCH 49/64] 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@redhat.com>
+---
+ server/red_parse_qxl.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 4449f2c..ceb2759 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -384,7 +384,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
+     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(RedMemSlotInfo *slots, int group_id,
+             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 * 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,
+@@ -1220,7 +1223,7 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+                         RedSurfaceCmd *red, QXLPHYSICAL addr)
+ {
+     QXLSurfaceCmd *qxl;
+-    size_t size;
++    uint64_t size;
+     int error;
+ 
+     qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
+@@ -1240,7 +1243,11 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+         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) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0050-Check-properly-surface-to-be-created.patch b/SOURCES/0050-Check-properly-surface-to-be-created.patch
new file mode 100644
index 0000000..f40ce03
--- /dev/null
+++ b/SOURCES/0050-Check-properly-surface-to-be-created.patch
@@ -0,0 +1,78 @@
+From b541f856f5c7fd70c1dad688306bcdfadfc2e4b9 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 16:02:59 +0100
+Subject: [PATCH 50/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_parse_qxl.c | 35 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index ceb2759..a7ca71d 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -1219,12 +1219,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);
+@@ -1243,9 +1261,24 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+         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 =
+-- 
+2.4.3
+
diff --git a/SOURCES/0050-Fix-race-condition-in-red_get_data_chunks_ptr.patch b/SOURCES/0050-Fix-race-condition-in-red_get_data_chunks_ptr.patch
deleted file mode 100644
index 71b0a38..0000000
--- a/SOURCES/0050-Fix-race-condition-in-red_get_data_chunks_ptr.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 20979131dee0f81972ca159e5f754d42890e75e6 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 12:12:19 +0100
-Subject: [PATCH 50/57] 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@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 c4b82be..7cc20e6 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.4.3
-
diff --git a/SOURCES/0051-Fix-buffer-reading-overflow.patch b/SOURCES/0051-Fix-buffer-reading-overflow.patch
new file mode 100644
index 0000000..db3b272
--- /dev/null
+++ b/SOURCES/0051-Fix-buffer-reading-overflow.patch
@@ -0,0 +1,38 @@
+From 214a0c88ecbac0229ddc2d7067a8a3ce9821df5c Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 10:00:37 +0100
+Subject: [PATCH 51/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 a7ca71d..01cba0f 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_error("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
+-- 
+2.4.3
+
diff --git a/SOURCES/0051-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch b/SOURCES/0051-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
deleted file mode 100644
index 331c3a2..0000000
--- a/SOURCES/0051-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 173645bea63ad31ba0d6d4c58a06272aa488fb92 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 12:14:55 +0100
-Subject: [PATCH 51/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 7cc20e6..fe3ae78 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.4.3
-
diff --git a/SOURCES/0052-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch b/SOURCES/0052-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
new file mode 100644
index 0000000..e075eb4
--- /dev/null
+++ b/SOURCES/0052-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
@@ -0,0 +1,48 @@
+From 0ede6619b828335a10ba94fe2739e01d5162d81c Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 13:09:35 +0100
+Subject: [PATCH 52/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_parse_qxl.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 01cba0f..3385f52 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,8 +371,8 @@ static int bitmap_consistent(SpiceBitmap *bitmap)
+ 
+     bpp = MAP_BITMAP_FMT_TO_BITS_PER_PIXEL[bitmap->format];
+ 
+-    if (bitmap->stride < ((bitmap->x * bpp + 7) / 8)) {
+-        spice_error("image stride too small for width: %d < ((%d * %d + 7) / 8) (%s=%d)\n",
++    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),
+                     bitmap->format);
+-- 
+2.4.3
+
diff --git a/SOURCES/0052-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch b/SOURCES/0052-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
deleted file mode 100644
index eb26991..0000000
--- a/SOURCES/0052-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From ffbe1b2e3bff5fec022030836a9319d57c6f94c5 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 12:28:54 +0100
-Subject: [PATCH 52/57] 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@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 fe3ae78..f183248 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.4.3
-
diff --git a/SOURCES/0053-Fix-race-condition-on-red_get_clip_rects.patch b/SOURCES/0053-Fix-race-condition-on-red_get_clip_rects.patch
new file mode 100644
index 0000000..f358959
--- /dev/null
+++ b/SOURCES/0053-Fix-race-condition-on-red_get_clip_rects.patch
@@ -0,0 +1,42 @@
+From eede1d8307b48016274077eea4dd9c7a296bf84a Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 10:01:51 +0100
+Subject: [PATCH 53/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 3385f52..affd3a2 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.4.3
+
diff --git a/SOURCES/0053-Fix-some-possible-overflows-in-red_get_string-for-32.patch b/SOURCES/0053-Fix-some-possible-overflows-in-red_get_string-for-32.patch
deleted file mode 100644
index 6875045..0000000
--- a/SOURCES/0053-Fix-some-possible-overflows-in-red_get_string-for-32.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 8f60fc6ec611aa6ad6fa31f3dfc8027462dbb442 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 8 Sep 2015 13:06:03 +0100
-Subject: [PATCH 53/57] Fix some possible overflows in red_get_string for 32
- bit
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/red_parse_qxl.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index f183248..668ce10 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -895,6 +895,11 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-         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);
-@@ -915,7 +920,8 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
-         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*)
--- 
-2.4.3
-
diff --git a/SOURCES/0054-Fix-race-in-red_get_image.patch b/SOURCES/0054-Fix-race-in-red_get_image.patch
new file mode 100644
index 0000000..ac9cc18
--- /dev/null
+++ b/SOURCES/0054-Fix-race-in-red_get_image.patch
@@ -0,0 +1,77 @@
+From e4112afbe0f55df29068933e471fe348f79d4f04 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 10:04:10 +0100
+Subject: [PATCH 54/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_parse_qxl.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index affd3a2..84ea526 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -397,6 +397,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
+     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(RedMemSlotInfo *slots, int group_id,
+     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(RedMemSlotInfo *slots, int group_id,
+         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;
+             }
+-- 
+2.4.3
+
diff --git a/SOURCES/0054-Make-sure-we-can-read-QXLPathSeg-structures.patch b/SOURCES/0054-Make-sure-we-can-read-QXLPathSeg-structures.patch
deleted file mode 100644
index f363968..0000000
--- a/SOURCES/0054-Make-sure-we-can-read-QXLPathSeg-structures.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 289301f33c7da81fcb034448d96e8c276b4fc06a Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 15 Sep 2015 16:25:17 +0100
-Subject: [PATCH 54/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 668ce10..4663bfd 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.4.3
-
diff --git a/SOURCES/0055-Avoid-race-condition-copying-segments-in-red_get_pat.patch b/SOURCES/0055-Avoid-race-condition-copying-segments-in-red_get_pat.patch
deleted file mode 100644
index 51c989c..0000000
--- a/SOURCES/0055-Avoid-race-condition-copying-segments-in-red_get_pat.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 14f53eef04c38a3c537a1a1012c2f7101a298194 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 15 Sep 2015 16:38:23 +0100
-Subject: [PATCH 55/57] 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@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@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 4663bfd..c1df8e8 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.4.3
-
diff --git a/SOURCES/0055-Fix-race-condition-in-red_get_string.patch b/SOURCES/0055-Fix-race-condition-in-red_get_string.patch
new file mode 100644
index 0000000..a8a6cb4
--- /dev/null
+++ b/SOURCES/0055-Fix-race-condition-in-red_get_string.patch
@@ -0,0 +1,62 @@
+From ee52db855a3b25965d5e363d64831864efe3f4f3 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 10:05:20 +0100
+Subject: [PATCH 55/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_parse_qxl.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 84ea526..2d4636e 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -809,6 +809,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+     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) {
+@@ -825,13 +826,15 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+     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);
+@@ -848,11 +851,11 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+         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);
+-- 
+2.4.3
+
diff --git a/SOURCES/0056-Fix-integer-overflow-computing-glyph_size-in-red_get.patch b/SOURCES/0056-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
new file mode 100644
index 0000000..24c253f
--- /dev/null
+++ b/SOURCES/0056-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
@@ -0,0 +1,63 @@
+From d6307f37304bddf6d76c42a6bdd8475ccab9582d Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 10:13:24 +0100
+Subject: [PATCH 56/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 2d4636e..c4b82be 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -807,7 +807,9 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+     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;
+ 
+@@ -846,7 +848,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+     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]);
+     }
+@@ -867,7 +869,7 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+         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]);
+-- 
+2.4.3
+
diff --git a/SOURCES/0056-Prevent-data_size-to-be-set-independently-from-data.patch b/SOURCES/0056-Prevent-data_size-to-be-set-independently-from-data.patch
deleted file mode 100644
index a78ea9a..0000000
--- a/SOURCES/0056-Prevent-data_size-to-be-set-independently-from-data.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From c2cdd1daf8edceec8adbb456dca656efe3648eec Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Thu, 17 Sep 2015 14:28:36 +0100
-Subject: [PATCH 56/57] 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@redhat.com>
----
- server/red_parse_qxl.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index c1df8e8..8e3dd55 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -1391,6 +1391,7 @@ static int red_get_cursor(RedMemSlotInfo *slots, int group_id,
-     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) {
--- 
-2.4.3
-
diff --git a/SOURCES/0057-Fix-race-condition-in-red_get_data_chunks_ptr.patch b/SOURCES/0057-Fix-race-condition-in-red_get_data_chunks_ptr.patch
new file mode 100644
index 0000000..d128555
--- /dev/null
+++ b/SOURCES/0057-Fix-race-condition-in-red_get_data_chunks_ptr.patch
@@ -0,0 +1,66 @@
+From a1ead07b6a0facefafb959542f3088f427c7eb2d Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 12:12:19 +0100
+Subject: [PATCH 57/64] 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@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 c4b82be..7cc20e6 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.4.3
+
diff --git a/SOURCES/0057-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch b/SOURCES/0057-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
deleted file mode 100644
index b7bf58f..0000000
--- a/SOURCES/0057-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 5580cac5502cd518adad0a3682fd53aeeaf86a86 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Thu, 17 Sep 2015 15:01:05 +0100
-Subject: [PATCH 57/57] Prevent leak if size from red_get_data_chunks don't
- match in red_get_image
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/red_parse_qxl.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
-index 8e3dd55..bd0c408 100644
---- a/server/red_parse_qxl.c
-+++ b/server/red_parse_qxl.c
-@@ -530,6 +530,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
-                                        &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(RedMemSlotInfo *slots, int group_id,
-                                        &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,
--- 
-2.4.3
-
diff --git a/SOURCES/0058-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch b/SOURCES/0058-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
new file mode 100644
index 0000000..f28db57
--- /dev/null
+++ b/SOURCES/0058-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
@@ -0,0 +1,75 @@
+From 098e6e9e479a1188c5b5050ac8a0d4f495ec4842 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 12:14:55 +0100
+Subject: [PATCH 58/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 7cc20e6..fe3ae78 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.4.3
+
diff --git a/SOURCES/0059-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch b/SOURCES/0059-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
new file mode 100644
index 0000000..2f11b59
--- /dev/null
+++ b/SOURCES/0059-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
@@ -0,0 +1,102 @@
+From f89da55f4c4fcc09f201562854f3768911fdab07 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 12:28:54 +0100
+Subject: [PATCH 59/64] 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@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 fe3ae78..f183248 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.4.3
+
diff --git a/SOURCES/0060-Fix-some-possible-overflows-in-red_get_string-for-32.patch b/SOURCES/0060-Fix-some-possible-overflows-in-red_get_string-for-32.patch
new file mode 100644
index 0000000..b94f03f
--- /dev/null
+++ b/SOURCES/0060-Fix-some-possible-overflows-in-red_get_string-for-32.patch
@@ -0,0 +1,41 @@
+From b61b33beae8b7560d05fe0d8349446bc16d08c62 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 8 Sep 2015 13:06:03 +0100
+Subject: [PATCH 60/64] Fix some possible overflows in red_get_string for 32
+ bit
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red_parse_qxl.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index f183248..668ce10 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -895,6 +895,11 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+         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);
+@@ -915,7 +920,8 @@ static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id,
+         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*)
+-- 
+2.4.3
+
diff --git a/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch b/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch
new file mode 100644
index 0000000..ad6bc16
--- /dev/null
+++ b/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch
@@ -0,0 +1,40 @@
+From 13dadd08709caa8e736cbbc886f5f8ba7bad7785 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 15 Sep 2015 16:25:17 +0100
+Subject: [PATCH 61/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 668ce10..4663bfd 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.4.3
+
diff --git a/SOURCES/0062-Avoid-race-condition-copying-segments-in-red_get_pat.patch b/SOURCES/0062-Avoid-race-condition-copying-segments-in-red_get_pat.patch
new file mode 100644
index 0000000..25da97b
--- /dev/null
+++ b/SOURCES/0062-Avoid-race-condition-copying-segments-in-red_get_pat.patch
@@ -0,0 +1,31 @@
+From a2510f4df1c01a48515504c25cd9f0d9d1e839d0 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 15 Sep 2015 16:38:23 +0100
+Subject: [PATCH 62/64] 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@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@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 4663bfd..c1df8e8 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.4.3
+
diff --git a/SOURCES/0063-Prevent-data_size-to-be-set-independently-from-data.patch b/SOURCES/0063-Prevent-data_size-to-be-set-independently-from-data.patch
new file mode 100644
index 0000000..1ccbb11
--- /dev/null
+++ b/SOURCES/0063-Prevent-data_size-to-be-set-independently-from-data.patch
@@ -0,0 +1,29 @@
+From acda240cbeb8a15aafd73b55a22fd3dfa7f03df1 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Thu, 17 Sep 2015 14:28:36 +0100
+Subject: [PATCH 63/64] 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@redhat.com>
+---
+ server/red_parse_qxl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index c1df8e8..8e3dd55 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -1391,6 +1391,7 @@ static int red_get_cursor(RedMemSlotInfo *slots, int group_id,
+     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) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0064-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch b/SOURCES/0064-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
new file mode 100644
index 0000000..7b1a381
--- /dev/null
+++ b/SOURCES/0064-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
@@ -0,0 +1,34 @@
+From ffa092aa729613de9fe9f7f59beea4338b324f5c Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Thu, 17 Sep 2015 15:01:05 +0100
+Subject: [PATCH 64/64] Prevent leak if size from red_get_data_chunks don't
+ match in red_get_image
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+---
+ server/red_parse_qxl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
+index 8e3dd55..bd0c408 100644
+--- a/server/red_parse_qxl.c
++++ b/server/red_parse_qxl.c
+@@ -530,6 +530,7 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
+                                        &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(RedMemSlotInfo *slots, int group_id,
+                                        &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,
+-- 
+2.4.3
+
diff --git a/SPECS/spice.spec b/SPECS/spice.spec
index f24555c..25eeb81 100644
--- a/SPECS/spice.spec
+++ b/SPECS/spice.spec
@@ -1,6 +1,6 @@
 Name:           spice
 Version:        0.12.4
-Release:        9%{?dist}.3
+Release:        15%{?dist}
 Summary:        Implements the SPICE protocol
 Group:          User Interface/Desktops
 License:        LGPLv2+
@@ -43,26 +43,34 @@ Patch34: 0034-Validate-surface-bounding-box-before-using-it.patch
 Patch35: 0035-migration-Don-t-assert-if-MIGRATE_DATA-comes-before-.patch
 Patch36: 0036-server-fix-crash-when-restarting-VM-with-old-client.patch
 Patch37: 0037-Use-TLS-version-1.0-or-better.patch
-Patch38: 0038-Avoid-race-conditions-reading-monitor-configs-from-g.patch
-Patch39: 0039-worker-validate-correctly-surfaces.patch
-Patch40: 0040-worker-avoid-double-free-or-double-create-of-surface.patch
-Patch41: 0041-Define-a-constant-to-limit-data-from-guest.patch
-Patch42: 0042-Fix-some-integer-overflow-causing-large-memory-alloc.patch
-Patch43: 0043-Check-properly-surface-to-be-created.patch
-Patch44: 0044-Fix-buffer-reading-overflow.patch
-Patch45: 0045-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
-Patch46: 0046-Fix-race-condition-on-red_get_clip_rects.patch
-Patch47: 0047-Fix-race-in-red_get_image.patch
-Patch48: 0048-Fix-race-condition-in-red_get_string.patch
-Patch49: 0049-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
-Patch50: 0050-Fix-race-condition-in-red_get_data_chunks_ptr.patch
-Patch51: 0051-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
-Patch52: 0052-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
-Patch53: 0053-Fix-some-possible-overflows-in-red_get_string-for-32.patch
-Patch54: 0054-Make-sure-we-can-read-QXLPathSeg-structures.patch
-Patch55: 0055-Avoid-race-condition-copying-segments-in-red_get_pat.patch
-Patch56: 0056-Prevent-data_size-to-be-set-independently-from-data.patch
-Patch57: 0057-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
+Patch38: 0038-Add-const-to-test_capability-first-argument.patch
+Patch39: 0039-Introduce-red_link_info_test_capability.patch
+Patch40: 0040-Don-t-set-SpiceLinkReply-pub_key-if-client-advertise.patch
+Patch41: 0041-server-don-t-assert-on-invalid-client-message.patch
+Patch42: 0042-Don-t-truncate-large-now-values-in-_spice_timer_set.patch
+Patch43: 0043-Avoid-race-conditions-reading-monitor-configs-from-g.patch
+Patch44: 0044-Lock-the-pixmap-image-cache-for-the-entire-fill_bits.patch
+Patch45: 0045-reds-Assure-we-don-t-have-stale-statistic-files-befo.patch
+Patch46: 0046-worker-validate-correctly-surfaces.patch
+Patch47: 0047-worker-avoid-double-free-or-double-create-of-surface.patch
+Patch48: 0048-Define-a-constant-to-limit-data-from-guest.patch
+Patch49: 0049-Fix-some-integer-overflow-causing-large-memory-alloc.patch
+Patch50: 0050-Check-properly-surface-to-be-created.patch
+Patch51: 0051-Fix-buffer-reading-overflow.patch
+Patch52: 0052-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch
+Patch53: 0053-Fix-race-condition-on-red_get_clip_rects.patch
+Patch54: 0054-Fix-race-in-red_get_image.patch
+Patch55: 0055-Fix-race-condition-in-red_get_string.patch
+Patch56: 0056-Fix-integer-overflow-computing-glyph_size-in-red_get.patch
+Patch57: 0057-Fix-race-condition-in-red_get_data_chunks_ptr.patch
+Patch58: 0058-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch
+Patch59: 0059-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch
+Patch60: 0060-Fix-some-possible-overflows-in-red_get_string-for-32.patch
+Patch61: 0061-Make-sure-we-can-read-QXLPathSeg-structures.patch
+Patch62: 0062-Avoid-race-condition-copying-segments-in-red_get_pat.patch
+Patch63: 0063-Prevent-data_size-to-be-set-independently-from-data.patch
+Patch64: 0064-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch
+
 
 # https://bugzilla.redhat.com/show_bug.cgi?id=613529
 %if 0%{?rhel}
@@ -175,6 +183,13 @@ using spice-server, you will need to install spice-server-devel.
 %patch55 -p1
 %patch56 -p1
 %patch57 -p1
+%patch58 -p1
+%patch59 -p1
+%patch60 -p1
+%patch61 -p1
+%patch62 -p1
+%patch63 -p1
+%patch64 -p1
 
 
 %build
@@ -205,18 +220,37 @@ mkdir -p %{buildroot}%{_libexecdir}
 
 
 %changelog
-* Wed Sep 23 2015 Frediano Ziglio <fziglio@redhat.com> 0.12.4-9.3
+* Wed Sep 23 2015 Frediano Ziglio <fziglio@redhat.com> 0.12.4-15
 - CVE-2015-5260 CVE-2015-5261 fixed various security flaws
-  Resolves: rhbz#1262771
+  Resolves: rhbz#1267134
 
-* Tue Sep 15 2015 Frediano Ziglio <fziglio@redhat.com> 0.12.4-9.2
+* Thu Sep 10 2015 Frediano Ziglio <fziglio@redhat.com> 0.12.4-14
 - Validate surface_id
-  Resolves: rhbz#1262771
-
-* Tue Jul 21 2015 Christophe Fergeau <cfergeau@redhat.com> 0.12.4-9.1
-- Avoid race conditions reading monitor configs from guest. This race could
-  trigger memory corruption host-side
-  Resolves: rhbz#1239127
+  Resolves: rhbz#1260971
+
+* Tue Jul 21 2015 Frediano Ziglio <fziglio@redhat.com> 0.12.4-13
+- Clean stale statistics file before creating a new one
+  Resolves: rhbz#1177326
+
+* Fri Jul 10 2015 Fabiano FidĂȘncio <fidencio@redhat.com> 0.12.4-12
+- Fix a backport issue on Patch0040.
+  Related: rhbz#1071176
+  Resolves: rhbz#1241860
+
+* Thu Jul 09 2015 Fabiano FidĂȘncio <fidencio@redhat.com> 0.12.4-11
+- Don't assert on invalid client message
+  Resolves: rhbz#1227410
+- Don't truncate large 'now' values in _spice_timer_set
+  Resolves: rhbz#1227408
+- Avoid race conditions reading monitor configs from guest
+  Resolves: rhbz#1239128
+- Lock the pixmap image cache for the entire fill_bits call
+  Resolves: rhbz#1235443
+
+* Wed Jul 08 2015 Fabiano FidĂȘncio <fidencio@redhat.com> 0.12.4-10
+- Fix qemu segmentation fault (core dumped) when boot KVM guest with
+  spice in FIPS enabled mode.
+  Resolves: rhbz#1071176
 
 * Mon Jan 05 2015 Marc-Andre Lureau <marcandre.lureau@redhat.com> 0.12.4-9
 - Allow recent TLS/SSL methods, block SSLv2/SSLv3. Resolves: rhbz#1175540