diff --git a/.gitignore b/.gitignore index a0cd66b..657c9f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/spice-0.12.4.tar.bz2 +SOURCES/spice-0.12.8.tar.bz2 diff --git a/.spice.metadata b/.spice.metadata index d2692cd..fc820d6 100644 --- a/.spice.metadata +++ b/.spice.metadata @@ -1 +1 @@ -5825cfcf8a786697e45a43aaf372f23b5c441336 SOURCES/spice-0.12.4.tar.bz2 +5f19057c5c17c1b6d601c386e6404b44ec77461f SOURCES/spice-0.12.8.tar.bz2 diff --git a/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch b/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch new file mode 100644 index 0000000..f9470ab --- /dev/null +++ b/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 20 Jul 2016 17:16:31 +0400 +Subject: [PATCH] Call migrate_end_complete() after falling back to switch-host +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Eventually, during a seamless migration, qemu may finish to migrate +before the spice client even finished to connect all channels to +destination and informed the server. In this case, +main_channel_client_migrate_src_complete() will fall back to +switch-host method, and reds_mig_fill_wait_disconnect() is called to +complete the migration (disconnecting all channels). + +reds_mig_cleanup() is called when all channels are disconnected, but +reds->mig_wait_connect is still TRUE, and it will call +migrate_connect_complete() instead of the expected +migrate_end_complete(). Setting reds->mig_wait_connect to FALSE when +reds_mig_fill_wait_disconnect() solves the issue. + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1352836 + +Signed-off-by: Marc-André Lureau +--- + server/reds.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/server/reds.c b/server/reds.c +index 61bf735..f40b65c 100644 +--- a/server/reds.c ++++ b/server/reds.c +@@ -2816,6 +2816,7 @@ static void reds_mig_fill_wait_disconnect(void) + wait_client->client = client; + ring_add(&reds->mig_wait_disconnect_clients, &wait_client->link); + } ++ reds->mig_wait_connect = FALSE; + reds->mig_wait_disconnect = TRUE; + core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT); + } diff --git a/SOURCES/0001-red_channel-prevent-adding-and-pushing-pipe-items-af.patch b/SOURCES/0001-red_channel-prevent-adding-and-pushing-pipe-items-af.patch deleted file mode 100644 index a324677..0000000 --- a/SOURCES/0001-red_channel-prevent-adding-and-pushing-pipe-items-af.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 24 Jul 2013 14:54:23 -0400 -Subject: [PATCH] red_channel: prevent adding and pushing pipe items after a - channel_client has diconnected - -Fixes: leaks of pipe items & "red_client_destroy: assertion `rcc->send_data.size == 0'" - -red_channel_disconnect clears the pipe. It is called only once. After, -it was called, not items should be added to the pipe. - -An example of when this assert can occur: -on_new_cursor_channel (red_worker.c), pushes 2 pipe items. -When it pushes the first pipe item, if the client has disconnected, -it can hit a socket error, and then, red_channel_client_disconnect is called. -The second call to adding a pipe item, will add the item to -the pipe. red_channel_client_pipe_add_type also calls -red_channel_client_push, which will update the send_data.size. -Then, the push will also hit a socket error, but red_channel_client_disconnect -won't clear the pending pipe item again, since it was already called. -When red_client_destory is called, we hit assertion `rcc->send_data.size -== 0'. -Note that if a pipe item is added to the pipe after -red_channel_client_disconnect was called, but without pushing it, -we should hit "spice_assert(rcc->pipe_size == 0)". ---- - server/red_channel.c | 30 ++++++++++++++++++++++++------ - 1 file changed, 24 insertions(+), 6 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 85d7ebc..fa4db7b 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -1515,9 +1515,23 @@ void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type) - item->type = type; - } - --void red_channel_client_pipe_add(RedChannelClient *rcc, PipeItem *item) -+static inline int validate_pipe_add(RedChannelClient *rcc, PipeItem *item) - { - spice_assert(rcc && item); -+ if (SPICE_UNLIKELY(!red_channel_client_is_connected(rcc))) { -+ spice_debug("rcc is disconnected %p", rcc); -+ red_channel_client_release_item(rcc, item, FALSE); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+void red_channel_client_pipe_add(RedChannelClient *rcc, PipeItem *item) -+{ -+ -+ if (!validate_pipe_add(rcc, item)) { -+ return; -+ } - rcc->pipe_size++; - ring_add(&rcc->pipe, &item->link); - } -@@ -1531,10 +1545,10 @@ void red_channel_client_pipe_add_push(RedChannelClient *rcc, PipeItem *item) - void red_channel_client_pipe_add_after(RedChannelClient *rcc, - PipeItem *item, PipeItem *pos) - { -- spice_assert(rcc); - spice_assert(pos); -- spice_assert(item); -- -+ if (!validate_pipe_add(rcc, item)) { -+ return; -+ } - rcc->pipe_size++; - ring_add_after(&item->link, &pos->link); - } -@@ -1548,14 +1562,18 @@ int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc, - void red_channel_client_pipe_add_tail_no_push(RedChannelClient *rcc, - PipeItem *item) - { -- spice_assert(rcc); -+ if (!validate_pipe_add(rcc, item)) { -+ return; -+ } - rcc->pipe_size++; - ring_add_before(&item->link, &rcc->pipe); - } - - void red_channel_client_pipe_add_tail(RedChannelClient *rcc, PipeItem *item) - { -- spice_assert(rcc); -+ if (!validate_pipe_add(rcc, item)) { -+ return; -+ } - rcc->pipe_size++; - ring_add_before(&item->link, &rcc->pipe); - red_channel_client_push(rcc); diff --git a/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch b/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch new file mode 100644 index 0000000..70339b3 --- /dev/null +++ b/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Mon, 28 Nov 2016 13:15:58 +0000 +Subject: [PATCH] Prevent possible DoS attempts during protocol handshake + +The limit for link message is specified using a 32 bit unsigned integer. +This could cause possible DoS due to excessive memory allocations and +some possible crashes. +For instance a value >= 2^31 causes a spice_assert to be triggered in +async_read_handler (reds-stream.c) due to an integer overflow at this +line: + + int n = async->end - async->now; + +This could be easily triggered with a program like + + #!/usr/bin/env python + + import socket + import time + from struct import pack + + server = '127.0.0.1' + port = 5900 + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((server, port)) + data = pack('<4sIII', 'REDQ', 2, 2, 0xaaaaaaaa) + s.send(data) + + time.sleep(1) + +without requiring any authentication (the same can be done +with TLS). + +Signed-off-by: Frediano Ziglio +--- + server/reds.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/server/reds.c b/server/reds.c +index f40b65c..86a33d5 100644 +--- a/server/reds.c ++++ b/server/reds.c +@@ -2202,7 +2202,8 @@ static void reds_handle_read_header_done(void *opaque) + + reds->peer_minor_version = header->minor_version; + +- if (header->size < sizeof(SpiceLinkMess)) { ++ /* the check for 4096 is to avoid clients to cause arbitrary big memory allocations */ ++ if (header->size < sizeof(SpiceLinkMess) || header->size > 4096) { + reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); + spice_warning("bad size %u", header->size); + reds_link_free(link); diff --git a/SOURCES/0002-red_channel-add-ref-count-to-RedClient.patch b/SOURCES/0002-red_channel-add-ref-count-to-RedClient.patch deleted file mode 100644 index 9cf3d1f..0000000 --- a/SOURCES/0002-red_channel-add-ref-count-to-RedClient.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Fri, 26 Jul 2013 13:45:16 -0400 -Subject: [PATCH] red_channel: add ref count to RedClient - ---- - server/red_channel.c | 23 ++++++++++++++++++++--- - server/red_channel.h | 17 +++++++++++++++-- - 2 files changed, 35 insertions(+), 5 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index fa4db7b..9433bef 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -1920,10 +1920,29 @@ RedClient *red_client_new(int migrated) - pthread_mutex_init(&client->lock, NULL); - client->thread_id = pthread_self(); - client->during_target_migrate = migrated; -+ client->refs = 1; - - return client; - } - -+RedClient *red_client_ref(RedClient *client) -+{ -+ spice_assert(client); -+ client->refs++; -+ return client; -+} -+ -+RedClient *red_client_unref(RedClient *client) -+{ -+ if (!--client->refs) { -+ spice_debug("release client=%p", client); -+ pthread_mutex_destroy(&client->lock); -+ free(client); -+ return NULL; -+ } -+ return client; -+} -+ - /* client mutex should be locked before this call */ - static void red_channel_client_set_migration_seamless(RedChannelClient *rcc) - { -@@ -2000,9 +2019,7 @@ void red_client_destroy(RedClient *client) - spice_assert(rcc->send_data.size == 0); - red_channel_client_destroy(rcc); - } -- -- pthread_mutex_destroy(&client->lock); -- free(client); -+ red_client_unref(client); - } - - /* client->lock should be locked */ -diff --git a/server/red_channel.h b/server/red_channel.h -index ba299b6..0dd73ea 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -561,10 +561,25 @@ struct RedClient { - is called */ - int seamless_migrate; - int num_migrated_channels; /* for seamless - number of channels that wait for migrate data*/ -+ int refs; - }; - - RedClient *red_client_new(int migrated); - -+/* -+ * disconnects all the client's channels (should be called from the client's thread) -+ */ -+void red_client_destroy(RedClient *client); -+ -+RedClient *red_client_ref(RedClient *client); -+ -+/* -+ * releases the client resources when refs == 0. -+ * We assume the red_client_derstroy was called before -+ * we reached refs==0 -+ */ -+RedClient *red_client_unref(RedClient *client); -+ - MainChannelClient *red_client_get_main(RedClient *client); - // main should be set once before all the other channels are created - void red_client_set_main(RedClient *client, MainChannelClient *mcc); -@@ -580,7 +595,5 @@ void red_client_semi_seamless_migrate_complete(RedClient *client); /* dst side * - int red_client_during_migrate_at_target(RedClient *client); - - void red_client_migrate(RedClient *client); --// disconnects all the client's channels (should be called from the client's thread) --void red_client_destroy(RedClient *client); - - #endif diff --git a/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch b/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch new file mode 100644 index 0000000..5571a12 --- /dev/null +++ b/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Mon, 28 Nov 2016 13:15:58 +0000 +Subject: [PATCH] Prevent integer overflows in capability checks + +The limits for capabilities are specified using 32 bit unsigned integers. +This could cause possible integer overflows causing buffer overflows. +For instance the sum of num_common_caps and num_caps can be 0 avoiding +additional checks. +As the link message is now capped to 4096 and the capabilities are +contained in the link message, this commit limits the capabilities +to 1024 (capabilities are expressed in number of uint32_t items). + +Signed-off-by: Frediano Ziglio +--- + server/reds.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/server/reds.c b/server/reds.c +index 86a33d5..c639aa3 100644 +--- a/server/reds.c ++++ b/server/reds.c +@@ -2113,6 +2113,14 @@ static void reds_handle_read_link_done(void *opaque) + num_caps = link_mess->num_common_caps + link_mess->num_channel_caps; + caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset); + ++ /* Prevent integer overflows. Currently we defined only 13 capabilities, ++ * I expect 1024 to be valid for quite a lot time */ ++ if (link_mess->num_channel_caps > 1024 || link_mess->num_common_caps > 1024) { ++ reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); ++ reds_link_free(link); ++ return; ++ } ++ + if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset > + link->link_header.size || + link_mess->caps_offset < sizeof(*link_mess))) { diff --git a/SOURCES/0003-main_dispatcher-add-ref-count-protection-to-RedClien.patch b/SOURCES/0003-main_dispatcher-add-ref-count-protection-to-RedClien.patch deleted file mode 100644 index 67b05c2..0000000 --- a/SOURCES/0003-main_dispatcher-add-ref-count-protection-to-RedClien.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Fri, 26 Jul 2013 13:49:24 -0400 -Subject: [PATCH] main_dispatcher: add ref count protection to RedClient - instances - ---- - server/main_dispatcher.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/server/main_dispatcher.c b/server/main_dispatcher.c -index e7a451a..bf160dd 100644 ---- a/server/main_dispatcher.c -+++ b/server/main_dispatcher.c -@@ -97,6 +97,7 @@ static void main_dispatcher_handle_migrate_complete(void *opaque, - MainDispatcherMigrateSeamlessDstCompleteMessage *mig_complete = payload; - - reds_on_client_seamless_migrate_complete(mig_complete->client); -+ red_client_unref(mig_complete->client); - } - - static void main_dispatcher_handle_mm_time_latency(void *opaque, -@@ -104,6 +105,7 @@ static void main_dispatcher_handle_mm_time_latency(void *opaque, - { - MainDispatcherMmTimeLatencyMessage *msg = payload; - reds_set_client_mm_time_latency(msg->client, msg->latency); -+ red_client_unref(msg->client); - } - - void main_dispatcher_seamless_migrate_dst_complete(RedClient *client) -@@ -115,7 +117,7 @@ void main_dispatcher_seamless_migrate_dst_complete(RedClient *client) - return; - } - -- msg.client = client; -+ msg.client = red_client_ref(client); - dispatcher_send_message(&main_dispatcher.base, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, - &msg); - } -@@ -129,7 +131,7 @@ void main_dispatcher_set_mm_time_latency(RedClient *client, uint32_t latency) - return; - } - -- msg.client = client; -+ msg.client = red_client_ref(client); - msg.latency = latency; - dispatcher_send_message(&main_dispatcher.base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY, - &msg); diff --git a/SOURCES/0004-decouple-disconnection-of-the-main-channel-from-clie.patch b/SOURCES/0004-decouple-disconnection-of-the-main-channel-from-clie.patch deleted file mode 100644 index eb015b9..0000000 --- a/SOURCES/0004-decouple-disconnection-of-the-main-channel-from-clie.patch +++ /dev/null @@ -1,235 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Thu, 25 Jul 2013 14:19:21 -0400 -Subject: [PATCH] decouple disconnection of the main channel from client - destruction - -Fixes rhbz#918169 - -Some channels make direct calls to reds/main_channel routines. If -these routines try to read/write to the socket, and they get socket -error, main_channel_client_on_disconnect is called, and triggers -red_client_destroy. In order to prevent accessing expired references -to RedClient, RedChannelClient, or other objects (inside the original call, after -red_client_destroy has been called) I made the call to -red_client_destroy asynchronous with respect to main_channel_client_on_disconnect. -I added MAIN_DISPATCHER_CLIENT_DISCONNECT to main_dispatcher. -main_channel_client_on_disconnect pushes this msg to the dispatcher, -instead of calling directly to reds_client_disconnect. - -The patch uses RedClient ref-count in order to handle a case where -reds_client_disconnect is called directly (e.g., when a new client connects while -another one is connected), while there is already CLIENT_DISCONNECT msg -pending in the main_dispatcher. - -Examples: -(1) snd_worker.c - - snd_disconnect_channel() - channel->cleanup() //snd_playback_cleanup - reds_enable_mm_timer() - . - . - main_channel_push_multi_media_time()...socket_error - . - . - red_client_destory() - . - . - snd_disconnect_channel() - channel->cleanup() - celt051_encoder_destroy() - celt051_encoder_destory() // double release - -Note that this bug could have been solved by changing the order of -calls: e.g., channel->stream = NULL before calling cleanup, and -some other changes + reference counting. However, I found other -places in the code with similar problems, and I looked for a general -solution, at least till we redesign red_channel to handle reference -counting more consistently. - -(2) inputs_channel.c - - inputs_connect() - main_channel_client_push_notify()...socket_error - . - . - red_client_destory() - . - . - red_channel_client_create() // refers to client which is already destroyed - -(3) reds.c - - reds_handle_main_link() - main_channel_push_init() ...socket error - . - . - red_client_destory() - . - . - main_channel_client_start_net_test(mcc) // refers to mcc which is already destroyed - - This can explain the assert in rhbz#964136, comment #1 (but not the hang that occurred before). ---- - server/main_channel.c | 9 +++++---- - server/main_dispatcher.c | 37 +++++++++++++++++++++++++++++++++++++ - server/main_dispatcher.h | 7 +++++++ - server/reds.c | 1 + - server/reds.h | 2 ++ - 5 files changed, 52 insertions(+), 4 deletions(-) - -diff --git a/server/main_channel.c b/server/main_channel.c -index 233e633..fe032a6 100644 ---- a/server/main_channel.c -+++ b/server/main_channel.c -@@ -46,6 +46,7 @@ - #include "red_common.h" - #include "reds.h" - #include "migration_protocol.h" -+#include "main_dispatcher.h" - - #define ZERO_BUF_SIZE 4096 - -@@ -175,13 +176,13 @@ int main_channel_is_connected(MainChannel *main_chan) - return red_channel_is_connected(&main_chan->base); - } - --// when disconnection occurs, let reds shutdown all channels. This will trigger the --// real disconnection of main channel -+/* -+ * When the main channel is disconnected, disconnect the entire client. -+ */ - static void main_channel_client_on_disconnect(RedChannelClient *rcc) - { - spice_printerr("rcc=%p", rcc); -- reds_client_disconnect(rcc->client); --// red_channel_client_disconnect(rcc); -+ main_dispatcher_client_disconnect(rcc->client); - } - - RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t connection_id) -diff --git a/server/main_dispatcher.c b/server/main_dispatcher.c -index bf160dd..dbe1037 100644 ---- a/server/main_dispatcher.c -+++ b/server/main_dispatcher.c -@@ -41,6 +41,7 @@ enum { - MAIN_DISPATCHER_CHANNEL_EVENT = 0, - MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, - MAIN_DISPATCHER_SET_MM_TIME_LATENCY, -+ MAIN_DISPATCHER_CLIENT_DISCONNECT, - - MAIN_DISPATCHER_NUM_MESSAGES - }; -@@ -59,6 +60,10 @@ typedef struct MainDispatcherMmTimeLatencyMessage { - uint32_t latency; - } MainDispatcherMmTimeLatencyMessage; - -+typedef struct MainDispatcherClientDisconnectMessage { -+ RedClient *client; -+} MainDispatcherClientDisconnectMessage; -+ - /* channel_event - calls core->channel_event, must be done in main thread */ - static void main_dispatcher_self_handle_channel_event( - int event, -@@ -108,6 +113,16 @@ static void main_dispatcher_handle_mm_time_latency(void *opaque, - red_client_unref(msg->client); - } - -+static void main_dispatcher_handle_client_disconnect(void *opaque, -+ void *payload) -+{ -+ MainDispatcherClientDisconnectMessage *msg = payload; -+ -+ spice_debug("client=%p", msg->client); -+ reds_client_disconnect(msg->client); -+ red_client_unref(msg->client); -+} -+ - void main_dispatcher_seamless_migrate_dst_complete(RedClient *client) - { - MainDispatcherMigrateSeamlessDstCompleteMessage msg; -@@ -137,6 +152,20 @@ void main_dispatcher_set_mm_time_latency(RedClient *client, uint32_t latency) - &msg); - } - -+void main_dispatcher_client_disconnect(RedClient *client) -+{ -+ MainDispatcherClientDisconnectMessage msg; -+ -+ if (!client->disconnecting) { -+ spice_debug("client %p", client); -+ msg.client = red_client_ref(client); -+ dispatcher_send_message(&main_dispatcher.base, MAIN_DISPATCHER_CLIENT_DISCONNECT, -+ &msg); -+ } else { -+ spice_debug("client %p already during disconnection", client); -+ } -+} -+ - static void dispatcher_handle_read(int fd, int event, void *opaque) - { - Dispatcher *dispatcher = opaque; -@@ -144,6 +173,11 @@ static void dispatcher_handle_read(int fd, int event, void *opaque) - dispatcher_handle_recv_read(dispatcher); - } - -+/* -+ * FIXME: -+ * Reds routines shouldn't be exposed. Instead reds.c should register the callbacks, -+ * and the corresponding operations should be made only via main_dispatcher. -+ */ - void main_dispatcher_init(SpiceCoreInterface *core) - { - memset(&main_dispatcher, 0, sizeof(main_dispatcher)); -@@ -160,4 +194,7 @@ void main_dispatcher_init(SpiceCoreInterface *core) - dispatcher_register_handler(&main_dispatcher.base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY, - main_dispatcher_handle_mm_time_latency, - sizeof(MainDispatcherMmTimeLatencyMessage), 0 /* no ack */); -+ dispatcher_register_handler(&main_dispatcher.base, MAIN_DISPATCHER_CLIENT_DISCONNECT, -+ main_dispatcher_handle_client_disconnect, -+ sizeof(MainDispatcherClientDisconnectMessage), 0 /* no ack */); - } -diff --git a/server/main_dispatcher.h b/server/main_dispatcher.h -index 0c79ca8..522c7f9 100644 ---- a/server/main_dispatcher.h -+++ b/server/main_dispatcher.h -@@ -7,6 +7,13 @@ - void main_dispatcher_channel_event(int event, SpiceChannelEventInfo *info); - void main_dispatcher_seamless_migrate_dst_complete(RedClient *client); - void main_dispatcher_set_mm_time_latency(RedClient *client, uint32_t latency); -+/* -+ * Disconnecting the client is always executed asynchronously, -+ * in order to protect from expired references in the routines -+ * that triggered the client destruction. -+ */ -+void main_dispatcher_client_disconnect(RedClient *client); -+ - void main_dispatcher_init(SpiceCoreInterface *core); - - #endif //MAIN_DISPATCHER_H -diff --git a/server/reds.c b/server/reds.c -index 30d0652..c66ddc4 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -537,6 +537,7 @@ void reds_client_disconnect(RedClient *client) - } - - if (!client || client->disconnecting) { -+ spice_debug("client %p already during disconnection", client); - return; - } - -diff --git a/server/reds.h b/server/reds.h -index c5c557d..1c5ae84 100644 ---- a/server/reds.h -+++ b/server/reds.h -@@ -136,6 +136,8 @@ void reds_handle_agent_mouse_event(const VDAgentMouseState *mouse_state); // use - extern struct SpiceCoreInterface *core; - - // Temporary measures to make splitting reds.c to inputs_channel.c easier -+ -+/* should be called only from main_dispatcher */ - void reds_client_disconnect(RedClient *client); - - // Temporary (?) for splitting main channel diff --git a/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch b/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch new file mode 100644 index 0000000..b5d265a --- /dev/null +++ b/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Tue, 29 Nov 2016 16:46:56 +0000 +Subject: [PATCH] main-channel: Prevent overflow reading messages from client + +Caller is supposed the function return a buffer able to store +size bytes. + +Signed-off-by: Frediano Ziglio +--- + server/main_channel.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/server/main_channel.c b/server/main_channel.c +index 0ecc9df..1fc3915 100644 +--- a/server/main_channel.c ++++ b/server/main_channel.c +@@ -1026,6 +1026,9 @@ static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, + + if (type == SPICE_MSGC_MAIN_AGENT_DATA) { + return reds_get_agent_data_buffer(mcc, size); ++ } else if (size > sizeof(main_chan->recv_buf)) { ++ /* message too large, caller will log a message and close the connection */ ++ return NULL; + } else { + return main_chan->recv_buf; + } diff --git a/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch b/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch new file mode 100644 index 0000000..70e183d --- /dev/null +++ b/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Thu, 26 Jan 2017 15:53:18 +0000 +Subject: [PATCH] reds: Check link header magic without waiting for the whole + header + +This allows the connection to early fail in case initial bytes +are not correct. +This allows for instance VNC client to graceful fail connecting +to a spice-server. This happens easily as the two protocols +share the same range of ports. + +This resolves rhbz#1416692. + +Signed-off-by: Frediano Ziglio +Acked-by: Christophe Fergeau +--- + server/reds.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/server/reds.c b/server/reds.c +index c639aa3..57a93c9 100644 +--- a/server/reds.c ++++ b/server/reds.c +@@ -2192,12 +2192,6 @@ static void reds_handle_read_header_done(void *opaque) + header->minor_version = GUINT32_FROM_LE(header->minor_version); + header->size = GUINT32_FROM_LE(header->size); + +- if (header->magic != SPICE_MAGIC) { +- reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC); +- reds_link_free(link); +- return; +- } +- + if (header->major_version != SPICE_VERSION_MAJOR) { + if (header->major_version > 0) { + reds_send_link_error(link, SPICE_LINK_ERR_VERSION_MISMATCH); +@@ -2227,13 +2221,31 @@ static void reds_handle_read_header_done(void *opaque) + link); + } + ++static void reds_handle_read_magic_done(void *opaque) ++{ ++ RedLinkInfo *link = (RedLinkInfo *)opaque; ++ const SpiceLinkHeader *header = &link->link_header; ++ ++ if (header->magic != SPICE_MAGIC) { ++ reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC); ++ reds_link_free(link); ++ return; ++ } ++ ++ reds_stream_async_read(link->stream, ++ ((uint8_t *)&link->link_header) + sizeof(header->magic), ++ sizeof(SpiceLinkHeader) - sizeof(header->magic), ++ reds_handle_read_header_done, ++ link); ++} ++ + static void reds_handle_new_link(RedLinkInfo *link) + { + reds_stream_set_async_error_handler(link->stream, reds_handle_link_error); + reds_stream_async_read(link->stream, + (uint8_t *)&link->link_header, +- sizeof(SpiceLinkHeader), +- reds_handle_read_header_done, ++ sizeof(link->link_header.magic), ++ reds_handle_read_magic_done, + link); + } + diff --git a/SOURCES/0005-reds-s-red_client_disconnect-red_channel_client_shut.patch b/SOURCES/0005-reds-s-red_client_disconnect-red_channel_client_shut.patch deleted file mode 100644 index e9851ed..0000000 --- a/SOURCES/0005-reds-s-red_client_disconnect-red_channel_client_shut.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Thu, 25 Jul 2013 14:25:24 -0400 -Subject: [PATCH] reds: s/red_client_disconnect/red_channel_client_shutdown - inside callbacks - -When we want to disconnect the main channel from a callback, it is -safer to use red_channel_client_shutdown, instead of directly -destroying the client. It is also more consistent with how other -channels treat errors. -red_channel_client_shutdown will trigger socket error in the main channel. -Then, main_channel_client_on_disconnect will be called, -and eventually, main_dispatcher_client_disconnect. - -I didn't replace calls to reds_disconnect/reds_client_disconnect in -places where those calls were safe && that might need immediate client -disconnection. ---- - server/reds.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/server/reds.c b/server/reds.c -index c66ddc4..ae87c90 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -879,7 +879,8 @@ static void vdi_port_on_free_self_token(void *opaque) - - static void vdi_port_remove_client(RedClient *client, void *opaque) - { -- reds_client_disconnect(client); -+ red_channel_client_shutdown(main_channel_client_get_base( -+ red_client_get_main(client))); - } - - /****************************************************************************/ -@@ -1009,7 +1010,7 @@ void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens) - - if (!client_added) { - spice_warning("failed to add client to agent"); -- reds_client_disconnect(rcc->client); -+ red_channel_client_shutdown(rcc); - return; - } - } else { -@@ -1126,7 +1127,7 @@ void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size) - reds_on_main_agent_monitors_config(mcc, message, size); - return; - case AGENT_MSG_FILTER_PROTO_ERROR: -- reds_disconnect(); -+ red_channel_client_shutdown(main_channel_client_get_base(mcc)); - return; - } - diff --git a/SOURCES/0006-snd_worker-fix-memory-leak-of-PlaybackChannel.patch b/SOURCES/0006-snd_worker-fix-memory-leak-of-PlaybackChannel.patch deleted file mode 100644 index da9d6f1..0000000 --- a/SOURCES/0006-snd_worker-fix-memory-leak-of-PlaybackChannel.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Thu, 25 Jul 2013 14:49:33 -0400 -Subject: [PATCH] snd_worker: fix memory leak of PlaybackChannel - -When the sequence of calls bellow occurs, the PlaybackChannel -is not released (snd_channel_put is not called for the -samples that refer to the channel). - - spice_server_playback_get_buffer - snd_channel_disconnect - spice_server_playback_put_samples ---- - server/snd_worker.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/server/snd_worker.c b/server/snd_worker.c -index d6ec47a..849f002 100644 ---- a/server/snd_worker.c -+++ b/server/snd_worker.c -@@ -1097,14 +1097,13 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance - PlaybackChannel *playback_channel; - AudioFrame *frame; - -- if (!sin->st->worker.connection) { -- return; -- } -- - frame = SPICE_CONTAINEROF(samples, AudioFrame, samples); - playback_channel = frame->channel; -- if (!snd_channel_put(&playback_channel->base) || !playback_channel->base.worker->connection) { -+ spice_assert(playback_channel); -+ if (!snd_channel_put(&playback_channel->base) || -+ sin->st->worker.connection != &playback_channel->base) { - /* lost last reference, channel has been destroyed previously */ -+ spice_info("audio samples belong to a disconnected channel"); - return; - } - spice_assert(playback_channel->base.active); diff --git a/SOURCES/0007-snd_worker-snd_disconnect_channel-don-t-call-snd_cha.patch b/SOURCES/0007-snd_worker-snd_disconnect_channel-don-t-call-snd_cha.patch deleted file mode 100644 index 5243444..0000000 --- a/SOURCES/0007-snd_worker-snd_disconnect_channel-don-t-call-snd_cha.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Thu, 25 Jul 2013 15:07:43 -0400 -Subject: [PATCH] snd_worker/snd_disconnect_channel: don't call snd_channel_put - if the channel has already been disconnected - -The snd channels has one reference as long as their socket is active. -The playback channel has an additional reference for each frame that is -currently filled by the sound device. -Once the channel is disconnected (the socket has been freed and the -first reference is released) snd_disconnect_channel shouldn't release -a reference again. ---- - server/snd_worker.c | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/server/snd_worker.c b/server/snd_worker.c -index 849f002..3827416 100644 ---- a/server/snd_worker.c -+++ b/server/snd_worker.c -@@ -212,21 +212,20 @@ static void snd_disconnect_channel(SndChannel *channel) - { - SndWorker *worker; - -- if (!channel) { -+ if (!channel || !channel->stream) { - spice_debug("not connected"); - return; - } - spice_debug("%p", channel); - worker = channel->worker; -- if (channel->stream) { -- channel->cleanup(channel); -- red_channel_client_disconnect(worker->connection->channel_client); -- core->watch_remove(channel->stream->watch); -- channel->stream->watch = NULL; -- reds_stream_free(channel->stream); -- channel->stream = NULL; -- spice_marshaller_destroy(channel->send_data.marshaller); -- } -+ channel->cleanup(channel); -+ red_channel_client_disconnect(worker->connection->channel_client); -+ worker->connection->channel_client = NULL; -+ core->watch_remove(channel->stream->watch); -+ channel->stream->watch = NULL; -+ reds_stream_free(channel->stream); -+ channel->stream = NULL; -+ spice_marshaller_destroy(channel->send_data.marshaller); - snd_channel_put(channel); - worker->connection = NULL; - } -@@ -897,6 +896,7 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i - int tos; - MainChannelClient *mcc = red_client_get_main(client); - -+ spice_assert(stream); - if ((flags = fcntl(stream->socket, F_GETFL)) == -1) { - spice_printerr("accept failed, %s", strerror(errno)); - goto error1; diff --git a/SOURCES/0008-log-improve-debug-information-related-to-client-disc.patch b/SOURCES/0008-log-improve-debug-information-related-to-client-disc.patch deleted file mode 100644 index 900ffdf..0000000 --- a/SOURCES/0008-log-improve-debug-information-related-to-client-disc.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Fri, 26 Jul 2013 12:15:00 -0400 -Subject: [PATCH] log: improve debug information related to client - disconnection - ---- - server/red_channel.c | 9 ++++++--- - server/snd_worker.c | 7 ++++--- - 2 files changed, 10 insertions(+), 6 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 9433bef..1a57db5 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -1100,6 +1100,7 @@ static void red_channel_client_ref(RedChannelClient *rcc) - static void red_channel_client_unref(RedChannelClient *rcc) - { - if (!--rcc->refs) { -+ spice_debug("destroy rcc=%p", rcc); - if (rcc->send_data.main.marshaller) { - spice_marshaller_destroy(rcc->send_data.main.marshaller); - } -@@ -1696,6 +1697,8 @@ static void red_channel_client_disconnect_dummy(RedChannelClient *rcc) - { - spice_assert(rcc->dummy); - if (ring_item_is_linked(&rcc->channel_link)) { -+ spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, rcc->channel, -+ rcc->channel->type, rcc->channel->id); - red_channel_remove_client(rcc); - } - rcc->dummy_connected = FALSE; -@@ -1703,8 +1706,6 @@ static void red_channel_client_disconnect_dummy(RedChannelClient *rcc) - - void red_channel_client_disconnect(RedChannelClient *rcc) - { -- spice_printerr("%p (channel %p type %d id %d)", rcc, rcc->channel, -- rcc->channel->type, rcc->channel->id); - if (rcc->dummy) { - red_channel_client_disconnect_dummy(rcc); - return; -@@ -1712,6 +1713,8 @@ void red_channel_client_disconnect(RedChannelClient *rcc) - if (!red_channel_client_is_connected(rcc)) { - return; - } -+ spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, rcc->channel, -+ rcc->channel->type, rcc->channel->id); - red_channel_client_pipe_clear(rcc); - if (rcc->stream->watch) { - rcc->channel->core->watch_remove(rcc->stream->watch); -@@ -1995,7 +1998,7 @@ void red_client_destroy(RedClient *client) - RingItem *link, *next; - RedChannelClient *rcc; - -- spice_printerr("destroy client with #channels %d", client->channels_num); -+ spice_printerr("destroy client %p with #channels=%d", client, client->channels_num); - if (!pthread_equal(pthread_self(), client->thread_id)) { - spice_warning("client->thread_id (0x%lx) != pthread_self (0x%lx)." - "If one of the threads is != io-thread && != vcpu-thread," -diff --git a/server/snd_worker.c b/server/snd_worker.c -index 3827416..ebddfcd 100644 ---- a/server/snd_worker.c -+++ b/server/snd_worker.c -@@ -201,8 +201,8 @@ static SndChannel *snd_channel_get(SndChannel *channel) - static SndChannel *snd_channel_put(SndChannel *channel) - { - if (!--channel->refs) { -+ spice_printerr("SndChannel=%p freed", channel); - free(channel); -- spice_printerr("sound channel freed"); - return NULL; - } - return channel; -@@ -216,7 +216,8 @@ static void snd_disconnect_channel(SndChannel *channel) - spice_debug("not connected"); - return; - } -- spice_debug("%p", channel); -+ spice_debug("SndChannel=%p rcc=%p type=%d", -+ channel, channel->channel_client, channel->channel_client->channel->type); - worker = channel->worker; - channel->cleanup(channel); - red_channel_client_disconnect(worker->connection->channel_client); -@@ -976,11 +977,11 @@ static void snd_disconnect_channel_client(RedChannelClient *rcc) - { - SndWorker *worker; - -- spice_debug(NULL); - spice_assert(rcc->channel); - spice_assert(rcc->channel->data); - worker = (SndWorker *)rcc->channel->data; - -+ spice_debug("channel-type=%d", rcc->channel->type); - if (worker->connection) { - spice_assert(worker->connection->channel_client == rcc); - snd_disconnect_channel(worker->connection); diff --git a/SOURCES/0009-red_worker-decrease-the-timeout-when-flushing-comman.patch b/SOURCES/0009-red_worker-decrease-the-timeout-when-flushing-comman.patch deleted file mode 100644 index fb53c25..0000000 --- a/SOURCES/0009-red_worker-decrease-the-timeout-when-flushing-comman.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Mon, 5 Aug 2013 12:10:15 -0400 -Subject: [PATCH] red_worker: decrease the timeout when flushing commands and - waiting for the client. - -150 seconds is way too long period for holding the guest driver and -waiting for a response for the client. This timeout was 15 seconds, but -when off-screen surfaces ware introduced it was arbitrarily multiplied by -10. -Other existing related bugs emphasize why it is important to decrease -the timeout: -(1) 994211 - the qxl driver waits for an async-io reponse for 60 seconds - and after that, it switches to sync-io mode. Not only that the - driver might use invalid data (since it didn't wait for the query to - complete), falling back to sync-io mode introduces other errors. -(2) 994175 - spice server sometimes doesn't recognize that the client - has disconnected. -(3) There might be cache inconsistency between the client and the server, -and then the display channel waits indefinitely for a cache item (e.g., bug -977998) - -This patch changes the timeout to 30 seconds. I tested it under wifi +emulating 2.5Mbps network, -together with playing video on the guest and changing resolutions in a loop. The timeout didn't expired -during my tests. - -This bug is related to rhbz#964136 (but from rhbz#964136 info it is still not -clear why the client wasn't responsive). ---- - server/red_worker.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/server/red_worker.c b/server/red_worker.c -index 73fe866..a4f0663 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -103,7 +103,7 @@ - #define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano - #define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro - --#define DISPLAY_CLIENT_TIMEOUT 15000000000ULL //nano -+#define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano - #define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec - #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro - -@@ -9721,7 +9721,7 @@ static inline void flush_display_commands(RedWorker *worker) - if (ring_is_empty) { - break; - } -- end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10; -+ end_time = red_now() + DISPLAY_CLIENT_TIMEOUT; - int sleep_count = 0; - for (;;) { - red_channel_push(&worker->display_channel->common.base); -@@ -9765,7 +9765,7 @@ static inline void flush_cursor_commands(RedWorker *worker) - if (ring_is_empty) { - break; - } -- end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10; -+ end_time = red_now() + DISPLAY_CLIENT_TIMEOUT; - int sleep_count = 0; - for (;;) { - red_channel_push(&worker->cursor_channel->common.base); diff --git a/SOURCES/0010-Fix-buffer-overflow-when-decrypting-client-SPICE-tic.patch b/SOURCES/0010-Fix-buffer-overflow-when-decrypting-client-SPICE-tic.patch deleted file mode 100644 index 6cc2375..0000000 --- a/SOURCES/0010-Fix-buffer-overflow-when-decrypting-client-SPICE-tic.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Fri, 23 Aug 2013 11:29:44 +0200 -Subject: [PATCH] Fix buffer overflow when decrypting client SPICE ticket - -reds_handle_ticket uses a fixed size 'password' buffer for the decrypted -password whose size is SPICE_MAX_PASSWORD_LENGTH. However, -RSA_private_decrypt which we call for the decryption expects the -destination buffer to be at least RSA_size(link->tiTicketing.rsa) -bytes long. On my spice-server build, SPICE_MAX_PASSWORD_LENGTH -is 60 while RSA_size() is 128, so we end up overflowing 'password' -when using long passwords (this was reproduced using the string: -'fullscreen=1proxy=#enter proxy here; e.g spice_proxy = http://[proxy]:[port]' -as a password). - -When the overflow occurs, QEMU dies with: -*** stack smashing detected ***: qemu-system-x86_64 terminated - -This commit ensures we use a corectly sized 'password' buffer, -and that it's correctly nul-terminated so that we can use strcmp -instead of strncmp. To keep using strncmp, we'd need to figure out -which one of 'password' and 'taTicket.password' is the smaller buffer, -and use that size. - -This fixes rhbz#999839 ---- - server/reds.c | 44 ++++++++++++++++++++++++++++++++------------ - 1 file changed, 32 insertions(+), 12 deletions(-) - -diff --git a/server/reds.c b/server/reds.c -index ae87c90..f9f185d 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1933,39 +1933,59 @@ static void reds_handle_link(RedLinkInfo *link) - static void reds_handle_ticket(void *opaque) - { - RedLinkInfo *link = (RedLinkInfo *)opaque; -- char password[SPICE_MAX_PASSWORD_LENGTH]; -+ char *password; - time_t ltime; -+ int password_size; - - //todo: use monotonic time - time(<ime); -- RSA_private_decrypt(link->tiTicketing.rsa_size, -- link->tiTicketing.encrypted_ticket.encrypted_data, -- (unsigned char *)password, link->tiTicketing.rsa, RSA_PKCS1_OAEP_PADDING); -+ if (RSA_size(link->tiTicketing.rsa) < SPICE_MAX_PASSWORD_LENGTH) { -+ spice_warning("RSA modulus size is smaller than SPICE_MAX_PASSWORD_LENGTH (%d < %d), " -+ "SPICE ticket sent from client may be truncated", -+ RSA_size(link->tiTicketing.rsa), SPICE_MAX_PASSWORD_LENGTH); -+ } -+ -+ password = g_malloc0(RSA_size(link->tiTicketing.rsa) + 1); -+ password_size = RSA_private_decrypt(link->tiTicketing.rsa_size, -+ link->tiTicketing.encrypted_ticket.encrypted_data, -+ (unsigned char *)password, -+ link->tiTicketing.rsa, -+ RSA_PKCS1_OAEP_PADDING); -+ if (password_size == -1) { -+ spice_warning("failed to decrypt RSA encrypted password: %s", -+ ERR_error_string(ERR_get_error(), NULL)); -+ goto error; -+ } -+ password[password_size] = '\0'; - - if (ticketing_enabled && !link->skip_auth) { - int expired = taTicket.expiration_time < ltime; - - if (strlen(taTicket.password) == 0) { -- reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); - spice_warning("Ticketing is enabled, but no password is set. " -- "please set a ticket first"); -- reds_link_free(link); -- return; -+ "please set a ticket first"); -+ goto error; - } - -- if (expired || strncmp(password, taTicket.password, SPICE_MAX_PASSWORD_LENGTH) != 0) { -+ if (expired || strcmp(password, taTicket.password) != 0) { - if (expired) { - spice_warning("Ticket has expired"); - } else { - spice_warning("Invalid password"); - } -- reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); -- reds_link_free(link); -- return; -+ goto error; - } - } - - reds_handle_link(link); -+ goto end; -+ -+error: -+ reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); -+ reds_link_free(link); -+ -+end: -+ g_free(password); - } - - static inline void async_read_clear_handlers(AsyncRead *obj) diff --git a/SOURCES/0011-server-move-three-functions-to-red_channel.patch b/SOURCES/0011-server-move-three-functions-to-red_channel.patch deleted file mode 100644 index c541150..0000000 --- a/SOURCES/0011-server-move-three-functions-to-red_channel.patch +++ /dev/null @@ -1,382 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Mon, 12 Aug 2013 15:01:42 +0300 -Subject: [PATCH] server: move three functions to red_channel - -Three blocking functions, one was split to leave the display channel -specific referencing of the DrawablePipeItem being sent inside -red_worker, but the rest (most) of the timeout logic was moved to -red_channel, including the associated constants. - -Moved functions: -red_channel_client_wait_pipe_item_sent -red_wait_outgoing_item -red_wait_all_sent - -Introduces red_time.h & red_time.c for a small helper function dealing -with time.h - -https://bugzilla.redhat.com/show_bug.cgi?id=1016795 -Conflicts: - server/red_worker.c ---- - server/red_channel.c | 106 ++++++++++++++++++++++++++++++++++++++++++++ - server/red_channel.h | 10 +++++ - server/red_time.c | 1 + - server/red_time.h | 15 +++++++ - server/red_worker.c | 121 +-------------------------------------------------- - 5 files changed, 134 insertions(+), 119 deletions(-) - create mode 100644 server/red_time.c - create mode 100644 server/red_time.h - -diff --git a/server/red_channel.c b/server/red_channel.c -index 1a57db5..555d376 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -38,6 +38,7 @@ - #include "red_channel.h" - #include "reds.h" - #include "main_dispatcher.h" -+#include "red_time.h" - - typedef struct EmptyMsgPipeItem { - PipeItem base; -@@ -47,6 +48,12 @@ typedef struct EmptyMsgPipeItem { - #define PING_TEST_TIMEOUT_MS 15000 - #define PING_TEST_IDLE_NET_TIMEOUT_MS 100 - -+#define DETACH_TIMEOUT 15000000000ULL //nano -+#define DETACH_SLEEP_DURATION 10000 //micro -+ -+#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano -+#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro -+ - enum QosPingState { - PING_STATE_NONE, - PING_STATE_TIMER, -@@ -2183,3 +2190,102 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel) - } - return sum; - } -+ -+void red_wait_outgoing_item(RedChannelClient *rcc) -+{ -+ uint64_t end_time; -+ int blocked; -+ -+ if (!red_channel_client_blocked(rcc)) { -+ return; -+ } -+ end_time = red_now() + DETACH_TIMEOUT; -+ spice_info("blocked"); -+ -+ do { -+ usleep(DETACH_SLEEP_DURATION); -+ red_channel_client_receive(rcc); -+ red_channel_client_send(rcc); -+ } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time); -+ -+ if (blocked) { -+ spice_warning("timeout"); -+ // TODO - shutting down the socket but we still need to trigger -+ // disconnection. Right now we wait for main channel to error for that. -+ red_channel_client_shutdown(rcc); -+ } else { -+ spice_assert(red_channel_client_no_item_being_sent(rcc)); -+ } -+} -+ -+/* TODO: more evil sync stuff. anything with the word wait in it's name. */ -+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -+ PipeItem *item) -+{ -+ uint64_t end_time; -+ int item_in_pipe; -+ -+ spice_info(NULL); -+ -+ end_time = red_now() + CHANNEL_PUSH_TIMEOUT; -+ -+ rcc->channel->channel_cbs.hold_item(rcc, item); -+ -+ if (red_channel_client_blocked(rcc)) { -+ red_channel_client_receive(rcc); -+ red_channel_client_send(rcc); -+ } -+ red_channel_client_push(rcc); -+ -+ while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) { -+ usleep(CHANNEL_PUSH_SLEEP_DURATION); -+ red_channel_client_receive(rcc); -+ red_channel_client_send(rcc); -+ red_channel_client_push(rcc); -+ } -+ -+ if (item_in_pipe) { -+ spice_warning("timeout"); -+ red_channel_client_disconnect(rcc); -+ } else { -+ red_wait_outgoing_item(rcc); -+ } -+ red_channel_client_release_item(rcc, item, TRUE); -+} -+ -+static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) -+{ -+ if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) { -+ red_channel_client_shutdown(rcc); -+ } else { -+ spice_assert(red_channel_client_no_item_being_sent(rcc)); -+ } -+} -+ -+void red_wait_all_sent(RedChannel *channel) -+{ -+ uint64_t end_time; -+ uint32_t max_pipe_size; -+ int blocked = FALSE; -+ -+ end_time = red_now() + DETACH_TIMEOUT; -+ -+ red_channel_push(channel); -+ while (((max_pipe_size = red_channel_max_pipe_size(channel)) || -+ (blocked = red_channel_any_blocked(channel))) && -+ red_now() < end_time) { -+ spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked); -+ usleep(DETACH_SLEEP_DURATION); -+ red_channel_receive(channel); -+ red_channel_send(channel); -+ red_channel_push(channel); -+ } -+ -+ if (max_pipe_size || blocked) { -+ spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)", -+ max_pipe_size, blocked); -+ red_channel_apply_clients(channel, rcc_shutdown_if_pending_send); -+ } else { -+ spice_assert(red_channel_no_item_being_sent(channel)); -+ } -+} -diff --git a/server/red_channel.h b/server/red_channel.h -index 0dd73ea..b2a3a6a 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -596,4 +596,14 @@ int red_client_during_migrate_at_target(RedClient *client); - - void red_client_migrate(RedClient *client); - -+/* blocking function */ -+void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -+ PipeItem *item); -+ -+/* blocking function */ -+void red_wait_outgoing_item(RedChannelClient *rcc); -+ -+/* blocking function */ -+void red_wait_all_sent(RedChannel *channel); -+ - #endif -diff --git a/server/red_time.c b/server/red_time.c -new file mode 100644 -index 0000000..8b13789 ---- /dev/null -+++ b/server/red_time.c -@@ -0,0 +1 @@ -+ -diff --git a/server/red_time.h b/server/red_time.h -new file mode 100644 -index 0000000..ffa97f2 ---- /dev/null -+++ b/server/red_time.h -@@ -0,0 +1,15 @@ -+#ifndef H_RED_TIME -+#define H_RED_TIME -+ -+#include -+ -+static inline uint64_t red_now(void) -+{ -+ struct timespec time; -+ -+ clock_gettime(CLOCK_MONOTONIC, &time); -+ -+ return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec; -+} -+ -+#endif -diff --git a/server/red_worker.c b/server/red_worker.c -index a4f0663..b3a957e 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -82,6 +82,7 @@ - #include "migration_protocol.h" - #include "spice_timer_queue.h" - #include "main_dispatcher.h" -+#include "red_time.h" - - //#define COMPRESS_STAT - //#define DUMP_BITMAP -@@ -97,12 +98,6 @@ - #define CMD_RING_POLL_TIMEOUT 10 //milli - #define CMD_RING_POLL_RETRIES 200 - --#define DETACH_TIMEOUT 15000000000ULL //nano --#define DETACH_SLEEP_DURATION 10000 //micro -- --#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano --#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro -- - #define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano - #define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec - #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro -@@ -1098,14 +1093,12 @@ static void cursor_channel_client_release_item_before_push(CursorChannelClient * - PipeItem *item); - static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc, - PipeItem *item); --static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item); - - #ifdef DUMP_BITMAP - static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id); - #endif - - static void red_push_monitors_config(DisplayChannelClient *dcc); --static inline uint64_t red_now(void); - - /* - * Macros to make iterating over stuff easier -@@ -2098,12 +2091,10 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int - } - - if (item) { -- red_wait_pipe_item_sent(&dcc->common.base, item); -+ red_channel_client_wait_pipe_item_sent(&dcc->common.base, item); - } - } - --static void red_wait_outgoing_item(RedChannelClient *rcc); -- - static void red_clear_surface_drawables_from_pipes(RedWorker *worker, int surface_id, - int force, int wait_for_outgoing_item) - { -@@ -5088,15 +5079,6 @@ static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint - red_release_cursor(worker, cursor_item); - } - --static inline uint64_t red_now(void) --{ -- struct timespec time; -- -- clock_gettime(CLOCK_MONOTONIC, &time); -- -- return ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec; --} -- - static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty) - { - QXLCommandExt ext_cmd; -@@ -10988,105 +10970,6 @@ typedef struct __attribute__ ((__packed__)) CursorData { - SpiceCursor _cursor; - } CursorData; - --static void red_wait_outgoing_item(RedChannelClient *rcc) --{ -- uint64_t end_time; -- int blocked; -- -- if (!red_channel_client_blocked(rcc)) { -- return; -- } -- end_time = red_now() + DETACH_TIMEOUT; -- spice_info("blocked"); -- -- do { -- usleep(DETACH_SLEEP_DURATION); -- red_channel_client_receive(rcc); -- red_channel_client_send(rcc); -- } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time); -- -- if (blocked) { -- spice_warning("timeout"); -- // TODO - shutting down the socket but we still need to trigger -- // disconnection. Right now we wait for main channel to error for that. -- red_channel_client_shutdown(rcc); -- } else { -- spice_assert(red_channel_client_no_item_being_sent(rcc)); -- } --} -- --static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) --{ -- if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) { -- red_channel_client_shutdown(rcc); -- } else { -- spice_assert(red_channel_client_no_item_being_sent(rcc)); -- } --} -- --static void red_wait_all_sent(RedChannel *channel) --{ -- uint64_t end_time; -- uint32_t max_pipe_size; -- int blocked = FALSE; -- -- end_time = red_now() + DETACH_TIMEOUT; -- -- red_channel_push(channel); -- while (((max_pipe_size = red_channel_max_pipe_size(channel)) || -- (blocked = red_channel_any_blocked(channel))) && -- red_now() < end_time) { -- spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked); -- usleep(DETACH_SLEEP_DURATION); -- red_channel_receive(channel); -- red_channel_send(channel); -- red_channel_push(channel); -- } -- -- if (max_pipe_size || blocked) { -- spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)", -- max_pipe_size, blocked); -- red_channel_apply_clients(channel, rcc_shutdown_if_pending_send); -- } else { -- spice_assert(red_channel_no_item_being_sent(channel)); -- } --} -- --/* TODO: more evil sync stuff. anything with the word wait in it's name. */ --static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item) --{ -- DrawablePipeItem *dpi; -- uint64_t end_time; -- int item_in_pipe; -- -- spice_info(NULL); -- dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item); -- ref_drawable_pipe_item(dpi); -- -- end_time = red_now() + CHANNEL_PUSH_TIMEOUT; -- -- if (red_channel_client_blocked(rcc)) { -- red_channel_client_receive(rcc); -- red_channel_client_send(rcc); -- } -- red_channel_client_push(rcc); -- -- while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) { -- usleep(CHANNEL_PUSH_SLEEP_DURATION); -- red_channel_client_receive(rcc); -- red_channel_client_send(rcc); -- red_channel_client_push(rcc); -- } -- -- if (item_in_pipe) { -- spice_warning("timeout"); -- red_channel_client_disconnect(rcc); -- } else { -- red_wait_outgoing_item(rcc); -- } -- put_drawable_pipe_item(dpi); --} -- - static void surface_dirty_region_to_rects(RedSurface *surface, - QXLRect *qxl_dirty_rects, - uint32_t num_dirty_rects, diff --git a/SOURCES/0012-server-s-red_wait_all_sent-red_channel_wait_all_sent.patch b/SOURCES/0012-server-s-red_wait_all_sent-red_channel_wait_all_sent.patch deleted file mode 100644 index 1a44cf0..0000000 --- a/SOURCES/0012-server-s-red_wait_all_sent-red_channel_wait_all_sent.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Mon, 12 Aug 2013 19:48:24 +0300 -Subject: [PATCH] server: s/red_wait_all_sent/red_channel_wait_all_sent/ - -https://bugzilla.redhat.com/show_bug.cgi?id=1016795 -(cherry picked from commit 9b8ff0428468b7f081fe6f2b27774af2d0b4dadf) ---- - server/red_channel.c | 2 +- - server/red_channel.h | 2 +- - server/red_worker.c | 6 +++--- - 3 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 555d376..6e43e0a 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -2262,7 +2262,7 @@ static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) - } - } - --void red_wait_all_sent(RedChannel *channel) -+void red_channel_wait_all_sent(RedChannel *channel) - { - uint64_t end_time; - uint32_t max_pipe_size; -diff --git a/server/red_channel.h b/server/red_channel.h -index b2a3a6a..9021b3f 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -604,6 +604,6 @@ void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, - void red_wait_outgoing_item(RedChannelClient *rcc); - - /* blocking function */ --void red_wait_all_sent(RedChannel *channel); -+void red_channel_wait_all_sent(RedChannel *channel); - - #endif -diff --git a/server/red_worker.c b/server/red_worker.c -index b3a957e..b93796c 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -11138,7 +11138,7 @@ static inline void red_cursor_reset(RedWorker *worker) - if (!worker->cursor_channel->common.during_target_migrate) { - red_pipes_add_verb(&worker->cursor_channel->common.base, SPICE_MSG_CURSOR_RESET); - } -- red_wait_all_sent(&worker->cursor_channel->common.base); -+ red_channel_wait_all_sent(&worker->cursor_channel->common.base); - } - } - -@@ -11421,8 +11421,8 @@ void handle_dev_stop(void *opaque, void *payload) - * purge the pipe, send destroy_all_surfaces - * to the client (there is no such message right now), and start - * from scratch on the destination side */ -- red_wait_all_sent(&worker->display_channel->common.base); -- red_wait_all_sent(&worker->cursor_channel->common.base); -+ red_channel_wait_all_sent(&worker->display_channel->common.base); -+ red_channel_wait_all_sent(&worker->cursor_channel->common.base); - } - - static int display_channel_wait_for_migrate_data(DisplayChannel *display) diff --git a/SOURCES/0013-red_worker-cleanup-red_clear_surface_drawables_from_.patch b/SOURCES/0013-red_worker-cleanup-red_clear_surface_drawables_from_.patch deleted file mode 100644 index b0c8bcc..0000000 --- a/SOURCES/0013-red_worker-cleanup-red_clear_surface_drawables_from_.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 11 Sep 2013 13:39:35 -0400 -Subject: [PATCH] red_worker: cleanup red_clear_surface_drawables_from_pipes - -(1) merge 'force' and 'wait_for_outgoing_item' to one parameter. - 'wait_for_outgoing_item' is a derivative of 'force'. -(2) move the call to red_wait_outgoing_item to red_clear_surface_drawables_from_pipe - -https://bugzilla.redhat.com/show_bug.cgi?id=1016795 ---- - server/red_worker.c | 30 ++++++++++++++++++------------ - 1 file changed, 18 insertions(+), 12 deletions(-) - -diff --git a/server/red_worker.c b/server/red_worker.c -index b93796c..f2c9220 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -2032,7 +2032,7 @@ static void red_current_clear(RedWorker *worker, int surface_id) - } - - static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id, -- int force) -+ int wait_if_used) - { - Ring *ring; - PipeItem *item; -@@ -2082,7 +2082,7 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int - - if (depend_found) { - spice_debug("surface %d dependent item found %p, %p", surface_id, drawable, item); -- if (force) { -+ if (wait_if_used) { - break; - } else { - return; -@@ -2090,24 +2090,30 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int - } - } - -+ if (!wait_if_used) { -+ return; -+ } -+ - if (item) { - red_channel_client_wait_pipe_item_sent(&dcc->common.base, item); -+ } else { -+ /* -+ * in case that the pipe didn't contain any item that is dependent on the surface, but -+ * there is one during sending. -+ */ -+ red_wait_outgoing_item(&dcc->common.base); - } - } - --static void red_clear_surface_drawables_from_pipes(RedWorker *worker, int surface_id, -- int force, int wait_for_outgoing_item) -+static void red_clear_surface_drawables_from_pipes(RedWorker *worker, -+ int surface_id, -+ int wait_if_used) - { - RingItem *item, *next; - DisplayChannelClient *dcc; - - WORKER_FOREACH_DCC_SAFE(worker, item, next, dcc) { -- red_clear_surface_drawables_from_pipe(dcc, surface_id, force); -- if (wait_for_outgoing_item) { -- // in case that the pipe didn't contain any item that is dependent on the surface, but -- // there is one during sending. -- red_wait_outgoing_item(&dcc->common.base); -- } -+ red_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used); - } - } - -@@ -4292,7 +4298,7 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface - otherwise "current" will hold items that other drawables may depend on, and then - red_current_clear will remove them from the pipe. */ - red_current_clear(worker, surface_id); -- red_clear_surface_drawables_from_pipes(worker, surface_id, FALSE, FALSE); -+ red_clear_surface_drawables_from_pipes(worker, surface_id, FALSE); - red_destroy_surface(worker, surface_id); - break; - default: -@@ -11099,7 +11105,7 @@ static inline void destroy_surface_wait(RedWorker *worker, int surface_id) - otherwise "current" will hold items that other drawables may depend on, and then - red_current_clear will remove them from the pipe. */ - red_current_clear(worker, surface_id); -- red_clear_surface_drawables_from_pipes(worker, surface_id, TRUE, TRUE); -+ red_clear_surface_drawables_from_pipes(worker, surface_id, TRUE); - } - - static void dev_destroy_surface_wait(RedWorker *worker, uint32_t surface_id) diff --git a/SOURCES/0014-red_channel-cleanup-of-red_channel_client-blocking-m.patch b/SOURCES/0014-red_channel-cleanup-of-red_channel_client-blocking-m.patch deleted file mode 100644 index d70f4a6..0000000 --- a/SOURCES/0014-red_channel-cleanup-of-red_channel_client-blocking-m.patch +++ /dev/null @@ -1,330 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 11 Sep 2013 13:31:21 -0400 -Subject: [PATCH] red_channel: cleanup of red_channel_client blocking methods - -(1) receive timeout as a parameter. -(2) add a return value and pass the handling - of failures to the calling routine. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016795 -(cherry picked from commit bcf9e64f134a6073c1e404efc8892c1cb453bd8a) ---- - server/red_channel.c | 73 ++++++++++++++++++++++++++-------------------------- - server/red_channel.h | 22 ++++++++++------ - server/red_worker.c | 55 ++++++++++++++++++++++++++++++--------- - 3 files changed, 93 insertions(+), 57 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 6e43e0a..228669b 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -48,11 +48,7 @@ typedef struct EmptyMsgPipeItem { - #define PING_TEST_TIMEOUT_MS 15000 - #define PING_TEST_IDLE_NET_TIMEOUT_MS 100 - --#define DETACH_TIMEOUT 15000000000ULL //nano --#define DETACH_SLEEP_DURATION 10000 //micro -- --#define CHANNEL_PUSH_TIMEOUT 30000000000ULL //nano --#define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro -+#define CHANNEL_BLOCKED_SLEEP_DURATION 10000 //micro - - enum QosPingState { - PING_STATE_NONE, -@@ -2191,43 +2187,49 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel) - return sum; - } - --void red_wait_outgoing_item(RedChannelClient *rcc) -+int red_channel_client_wait_outgoing_item(RedChannelClient *rcc, -+ int64_t timeout) - { - uint64_t end_time; - int blocked; - - if (!red_channel_client_blocked(rcc)) { -- return; -+ return TRUE; -+ } -+ if (timeout != -1) { -+ end_time = red_now() + timeout; - } -- end_time = red_now() + DETACH_TIMEOUT; - spice_info("blocked"); - - do { -- usleep(DETACH_SLEEP_DURATION); -+ usleep(CHANNEL_BLOCKED_SLEEP_DURATION); - red_channel_client_receive(rcc); - red_channel_client_send(rcc); -- } while ((blocked = red_channel_client_blocked(rcc)) && red_now() < end_time); -+ } while ((blocked = red_channel_client_blocked(rcc)) && -+ (timeout == -1 || red_now() < end_time)); - - if (blocked) { - spice_warning("timeout"); -- // TODO - shutting down the socket but we still need to trigger -- // disconnection. Right now we wait for main channel to error for that. -- red_channel_client_shutdown(rcc); -+ return FALSE; - } else { - spice_assert(red_channel_client_no_item_being_sent(rcc)); -+ return TRUE; - } - } - - /* TODO: more evil sync stuff. anything with the word wait in it's name. */ --void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -- PipeItem *item) -+int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -+ PipeItem *item, -+ int64_t timeout) - { - uint64_t end_time; - int item_in_pipe; - - spice_info(NULL); - -- end_time = red_now() + CHANNEL_PUSH_TIMEOUT; -+ if (timeout != -1) { -+ end_time = red_now() + timeout; -+ } - - rcc->channel->channel_cbs.hold_item(rcc, item); - -@@ -2237,55 +2239,52 @@ void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, - } - red_channel_client_push(rcc); - -- while((item_in_pipe = ring_item_is_linked(&item->link)) && (red_now() < end_time)) { -- usleep(CHANNEL_PUSH_SLEEP_DURATION); -+ while((item_in_pipe = ring_item_is_linked(&item->link)) && -+ (timeout == -1 || red_now() < end_time)) { -+ usleep(CHANNEL_BLOCKED_SLEEP_DURATION); - red_channel_client_receive(rcc); - red_channel_client_send(rcc); - red_channel_client_push(rcc); - } - -+ red_channel_client_release_item(rcc, item, TRUE); - if (item_in_pipe) { - spice_warning("timeout"); -- red_channel_client_disconnect(rcc); -- } else { -- red_wait_outgoing_item(rcc); -- } -- red_channel_client_release_item(rcc, item, TRUE); --} -- --static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) --{ -- if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) { -- red_channel_client_shutdown(rcc); -+ return FALSE; - } else { -- spice_assert(red_channel_client_no_item_being_sent(rcc)); -+ return red_channel_client_wait_outgoing_item(rcc, -+ timeout == -1 ? -1 : end_time - red_now()); - } - } - --void red_channel_wait_all_sent(RedChannel *channel) -+int red_channel_wait_all_sent(RedChannel *channel, -+ int64_t timeout) - { - uint64_t end_time; - uint32_t max_pipe_size; - int blocked = FALSE; - -- end_time = red_now() + DETACH_TIMEOUT; -+ if (timeout != -1) { -+ end_time = red_now() + timeout; -+ } - - red_channel_push(channel); - while (((max_pipe_size = red_channel_max_pipe_size(channel)) || - (blocked = red_channel_any_blocked(channel))) && -- red_now() < end_time) { -+ (timeout == -1 || red_now() < end_time)) { - spice_debug("pipe-size %u blocked %d", max_pipe_size, blocked); -- usleep(DETACH_SLEEP_DURATION); -+ usleep(CHANNEL_BLOCKED_SLEEP_DURATION); - red_channel_receive(channel); - red_channel_send(channel); - red_channel_push(channel); - } - - if (max_pipe_size || blocked) { -- spice_printerr("timeout: pending out messages exist (pipe-size %u, blocked %d)", -- max_pipe_size, blocked); -- red_channel_apply_clients(channel, rcc_shutdown_if_pending_send); -+ spice_warning("timeout: pending out messages exist (pipe-size %u, blocked %d)", -+ max_pipe_size, blocked); -+ return FALSE; - } else { - spice_assert(red_channel_no_item_being_sent(channel)); -+ return TRUE; - } - } -diff --git a/server/red_channel.h b/server/red_channel.h -index 9021b3f..fa11505 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -596,14 +596,20 @@ int red_client_during_migrate_at_target(RedClient *client); - - void red_client_migrate(RedClient *client); - --/* blocking function */ --void red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -- PipeItem *item); -- --/* blocking function */ --void red_wait_outgoing_item(RedChannelClient *rcc); -+/* -+ * blocking functions. -+ * -+ * timeout is in nano sec. -1 for no timeout. -+ * -+ * Return: TRUE if waiting succeeded. FALSE if timeout expired. -+ */ - --/* blocking function */ --void red_channel_wait_all_sent(RedChannel *channel); -+int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, -+ PipeItem *item, -+ int64_t timeout); -+int red_channel_client_wait_outgoing_item(RedChannelClient *rcc, -+ int64_t timeout); -+int red_channel_wait_all_sent(RedChannel *channel, -+ int64_t timeout); - - #endif -diff --git a/server/red_worker.c b/server/red_worker.c -index f2c9220..31f3cbb 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -98,6 +98,7 @@ - #define CMD_RING_POLL_TIMEOUT 10 //milli - #define CMD_RING_POLL_RETRIES 200 - -+#define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano - #define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano - #define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec - #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro -@@ -2031,8 +2032,12 @@ static void red_current_clear(RedWorker *worker, int surface_id) - } - } - --static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id, -- int wait_if_used) -+/* -+ * Return: TRUE if wait_if_used == FALSE, or otherwise, if all of the pipe items that -+ * are related to the surface have been cleared (or sent) from the pipe. -+ */ -+static int red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id, -+ int wait_if_used) - { - Ring *ring; - PipeItem *item; -@@ -2040,7 +2045,7 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int - RedChannelClient *rcc; - - if (!dcc) { -- return; -+ return TRUE; - } - - /* removing the newest drawables that their destination is surface_id and -@@ -2085,24 +2090,27 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int - if (wait_if_used) { - break; - } else { -- return; -+ return TRUE; - } - } - } - - if (!wait_if_used) { -- return; -+ return TRUE; - } - - if (item) { -- red_channel_client_wait_pipe_item_sent(&dcc->common.base, item); -+ return red_channel_client_wait_pipe_item_sent(&dcc->common.base, item, -+ DISPLAY_CLIENT_TIMEOUT); - } else { - /* - * in case that the pipe didn't contain any item that is dependent on the surface, but -- * there is one during sending. -+ * there is one during sending. Use a shorter timeout, since it is just one item - */ -- red_wait_outgoing_item(&dcc->common.base); -+ return red_channel_client_wait_outgoing_item(&dcc->common.base, -+ DISPLAY_CLIENT_SHORT_TIMEOUT); - } -+ return TRUE; - } - - static void red_clear_surface_drawables_from_pipes(RedWorker *worker, -@@ -2113,7 +2121,9 @@ static void red_clear_surface_drawables_from_pipes(RedWorker *worker, - DisplayChannelClient *dcc; - - WORKER_FOREACH_DCC_SAFE(worker, item, next, dcc) { -- red_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used); -+ if (!red_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used)) { -+ red_channel_client_disconnect(&dcc->common.base); -+ } - } - } - -@@ -11127,6 +11137,15 @@ void handle_dev_destroy_surface_wait(void *opaque, void *payload) - dev_destroy_surface_wait(worker, msg->surface_id); - } - -+static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) -+{ -+ if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) { -+ red_channel_client_shutdown(rcc); -+ } else { -+ spice_assert(red_channel_client_no_item_being_sent(rcc)); -+ } -+} -+ - static inline void red_cursor_reset(RedWorker *worker) - { - if (worker->cursor) { -@@ -11144,7 +11163,11 @@ static inline void red_cursor_reset(RedWorker *worker) - if (!worker->cursor_channel->common.during_target_migrate) { - red_pipes_add_verb(&worker->cursor_channel->common.base, SPICE_MSG_CURSOR_RESET); - } -- red_channel_wait_all_sent(&worker->cursor_channel->common.base); -+ if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, -+ DISPLAY_CLIENT_TIMEOUT)) { -+ red_channel_apply_clients(&worker->cursor_channel->common.base, -+ rcc_shutdown_if_pending_send); -+ } - } - } - -@@ -11427,8 +11450,16 @@ void handle_dev_stop(void *opaque, void *payload) - * purge the pipe, send destroy_all_surfaces - * to the client (there is no such message right now), and start - * from scratch on the destination side */ -- red_channel_wait_all_sent(&worker->display_channel->common.base); -- red_channel_wait_all_sent(&worker->cursor_channel->common.base); -+ if (!red_channel_wait_all_sent(&worker->display_channel->common.base, -+ DISPLAY_CLIENT_TIMEOUT)) { -+ red_channel_apply_clients(&worker->display_channel->common.base, -+ rcc_shutdown_if_pending_send); -+ } -+ if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, -+ DISPLAY_CLIENT_TIMEOUT)) { -+ red_channel_apply_clients(&worker->cursor_channel->common.base, -+ rcc_shutdown_if_pending_send); -+ } - } - - static int display_channel_wait_for_migrate_data(DisplayChannel *display) diff --git a/SOURCES/0015-red_worker-disconnect-the-channel-instead-of-shutdow.patch b/SOURCES/0015-red_worker-disconnect-the-channel-instead-of-shutdow.patch deleted file mode 100644 index adadd9e..0000000 --- a/SOURCES/0015-red_worker-disconnect-the-channel-instead-of-shutdow.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 11 Sep 2013 15:02:23 -0400 -Subject: [PATCH] red_worker: disconnect the channel instead of shutdown in - case of a blocking method failure - -rhbz#1004443 - -The methods that trigger waitings on the client pipe require that -the waiting will succeed in order to continue, or otherwise, that -all the living pipe items will be released (e.g., when -we must destroy a surface, we need that all its related pipe items will -be released). Shutdown of the socket will eventually trigger -red_channel_client_disconnect (*), which will empty the pipe. However, -if the blocking method failed, we need to empty the pipe synchronously. -It is not safe(**) to call red_channel_client_disconnect from ChannelCbs -, but all the blocking calls in red_worker are done from callbacks that -are triggered from the device. -To summarize, calling red_channel_client_disconnect instead of calling -red_channel_client_shutdown will immediately release all the pipe items that are -held by the channel client (by calling red_channel_client_pipe_clear). -If red_clear_surface_drawables_from_pipe timeouts, -red_channel_client_disconnect will make sure that the surface we wish to -release is not referenced by any pipe-item. - -(*) After a shutdown of a socket, we expect that later, when -red_peer_handle_incoming is called, it will encounter a socket -error and will call the channel's on_error callback which calls -red_channel_client_disconnect. - -(**) I believe it was not safe before commit 2d2121a17038bc0 (before adding ref -count to ChannelClient). However, I think it might still be unsafe, because -red_channel_client_disconnect sets rcc->stream to NULL, and rcc->stream -may be referred later inside a red_channel_client method unsafely. So instead -of checking if (stream != NULL) after calling callbacks, we try to avoid -calling red_channel_client_disconnect from callbacks. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016795 -(cherry picked from commit 90a4761249f84421b27d67a85262b1423b24fe04) ---- - server/red_worker.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/server/red_worker.c b/server/red_worker.c -index 31f3cbb..7a1c2d9 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -11137,10 +11137,10 @@ void handle_dev_destroy_surface_wait(void *opaque, void *payload) - dev_destroy_surface_wait(worker, msg->surface_id); - } - --static void rcc_shutdown_if_pending_send(RedChannelClient *rcc) -+static void rcc_disconnect_if_pending_send(RedChannelClient *rcc) - { - if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) { -- red_channel_client_shutdown(rcc); -+ red_channel_client_disconnect(rcc); - } else { - spice_assert(red_channel_client_no_item_being_sent(rcc)); - } -@@ -11166,7 +11166,7 @@ static inline void red_cursor_reset(RedWorker *worker) - if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, - DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->cursor_channel->common.base, -- rcc_shutdown_if_pending_send); -+ rcc_disconnect_if_pending_send); - } - } - } -@@ -11453,12 +11453,12 @@ void handle_dev_stop(void *opaque, void *payload) - if (!red_channel_wait_all_sent(&worker->display_channel->common.base, - DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->display_channel->common.base, -- rcc_shutdown_if_pending_send); -+ rcc_disconnect_if_pending_send); - } - if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, - DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->cursor_channel->common.base, -- rcc_shutdown_if_pending_send); -+ rcc_disconnect_if_pending_send); - } - } - diff --git a/SOURCES/0016-spice_timer_queue-don-t-call-timers-repeatedly.patch b/SOURCES/0016-spice_timer_queue-don-t-call-timers-repeatedly.patch deleted file mode 100644 index df997da..0000000 --- a/SOURCES/0016-spice_timer_queue-don-t-call-timers-repeatedly.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Tue, 13 Aug 2013 15:40:16 -0400 -Subject: [PATCH] spice_timer_queue: don't call timers repeatedly - -For channels that don't run as part of the main loop, we use -spice_timer_queue, while for the other channels we use -qemu timers support. The callbacks for setting timers are supplied to -red_channel via SpiceCoreInterface, and their behavior should be -consistent. qemu timers are called only once per each call to -timer_start. This patch assigns the same behaviour to spice_timer_queue. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016790 -(cherry picked from commit c1c08c289883455f025836f14eda7bfd86442ed7) ---- - server/spice_timer_queue.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/server/spice_timer_queue.c b/server/spice_timer_queue.c -index 833ab1d..8f6e9c8 100644 ---- a/server/spice_timer_queue.c -+++ b/server/spice_timer_queue.c -@@ -261,9 +261,7 @@ void spice_timer_queue_cb(void) - break; - } else { - timer->func(timer->opaque); -- if (timer->is_active) { -- _spice_timer_set(timer, timer->ms, now_ms); -- } -+ spice_timer_cancel(timer); - } - } - } diff --git a/SOURCES/0017-red_channel-add-on_input-callback-for-tracing-incomi.patch b/SOURCES/0017-red_channel-add-on_input-callback-for-tracing-incomi.patch deleted file mode 100644 index 1906655..0000000 --- a/SOURCES/0017-red_channel-add-on_input-callback-for-tracing-incomi.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 14 Aug 2013 09:38:12 -0400 -Subject: [PATCH] red_channel: add on_input callback for tracing incoming bytes - -The callback will be used in the next patch. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016790 -(cherry picked from commit d1e7142a0f90e2b977d2a73d26dc5b09d7771826) ---- - server/red_channel.c | 7 +++++++ - server/red_channel.h | 2 ++ - 2 files changed, 9 insertions(+) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 228669b..bc6ac8d 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -244,6 +244,7 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle - handler->cb->on_error(handler->opaque); - return; - } -+ handler->cb->on_input(handler->opaque, bytes_read); - handler->header_pos += bytes_read; - - if (handler->header_pos != handler->header.header_size) { -@@ -271,6 +272,7 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle - handler->cb->on_error(handler->opaque); - return; - } -+ handler->cb->on_input(handler->opaque, bytes_read); - handler->msg_pos += bytes_read; - if (handler->msg_pos != msg_size) { - return; -@@ -383,6 +385,10 @@ static void red_channel_client_on_output(void *opaque, int n) - stat_inc_counter(rcc->channel->out_bytes_counter, n); - } - -+static void red_channel_client_on_input(void *opaque, int n) -+{ -+} -+ - static void red_channel_client_default_peer_on_error(RedChannelClient *rcc) - { - red_channel_client_disconnect(rcc); -@@ -919,6 +925,7 @@ RedChannel *red_channel_create(int size, - channel->incoming_cb.handle_message = (handle_message_proc)handle_message; - channel->incoming_cb.on_error = - (on_incoming_error_proc)red_channel_client_default_peer_on_error; -+ channel->incoming_cb.on_input = red_channel_client_on_input; - channel->outgoing_cb.get_msg_size = red_channel_client_peer_get_out_msg_size; - channel->outgoing_cb.prepare = red_channel_client_peer_prepare_out_msg; - channel->outgoing_cb.on_block = red_channel_client_peer_on_out_block; -diff --git a/server/red_channel.h b/server/red_channel.h -index fa11505..64befff 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -74,6 +74,7 @@ typedef uint8_t *(*alloc_msg_recv_buf_proc)(void *opaque, uint16_t type, uint32_ - typedef void (*release_msg_recv_buf_proc)(void *opaque, - uint16_t type, uint32_t size, uint8_t *msg); - typedef void (*on_incoming_error_proc)(void *opaque); -+typedef void (*on_input_proc)(void *opaque, int n); - - typedef struct IncomingHandlerInterface { - handle_message_proc handle_message; -@@ -83,6 +84,7 @@ typedef struct IncomingHandlerInterface { - // The following is an optional alternative to handle_message, used if not null - spice_parse_channel_func_t parser; - handle_parsed_proc handle_parsed; -+ on_input_proc on_input; - } IncomingHandlerInterface; - - typedef struct IncomingHandler { diff --git a/SOURCES/0018-red_channel-add-option-to-monitor-whether-a-channel-.patch b/SOURCES/0018-red_channel-add-option-to-monitor-whether-a-channel-.patch deleted file mode 100644 index 77b2c62..0000000 --- a/SOURCES/0018-red_channel-add-option-to-monitor-whether-a-channel-.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 14 Aug 2013 10:10:37 -0400 -Subject: [PATCH] red_channel: add option to monitor whether a channel client - is alive - -rhbz#994175 - -When a client connection is closed surprisingly (i.e., without a FIN -segment), we cannot identify it by a socket error (which is the only -way by which we identified disconnections so far). -This patch allows a channel client to periodically check the state of -the connection and identify surprise disconnections. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016790 -(cherry picked from commit c8b808bb8211e756a5e2280da173010984b71680) ---- - server/red_channel.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ - server/red_channel.h | 14 ++++++ - 2 files changed, 133 insertions(+) - -diff --git a/server/red_channel.c b/server/red_channel.c -index bc6ac8d..5df8f14 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -57,6 +57,13 @@ enum QosPingState { - PING_STATE_LATENCY, - }; - -+enum ConnectivityState { -+ CONNECTIVITY_STATE_CONNECTED, -+ CONNECTIVITY_STATE_BLOCKED, -+ CONNECTIVITY_STATE_WAIT_PONG, -+ CONNECTIVITY_STATE_DISCONNECTED, -+}; -+ - static void red_channel_client_start_ping_timer(RedChannelClient *rcc, uint32_t timeout); - static void red_channel_client_cancel_ping_timer(RedChannelClient *rcc); - static void red_channel_client_restart_ping_timer(RedChannelClient *rcc); -@@ -66,6 +73,7 @@ static void red_client_add_channel(RedClient *client, RedChannelClient *rcc); - static void red_client_remove_channel(RedChannelClient *rcc); - static RedChannelClient *red_client_get_channel(RedClient *client, int type, int id); - static void red_channel_client_restore_main_sender(RedChannelClient *rcc); -+static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc); - - /* - * Lifetime of RedChannel, RedChannelClient and RedClient: -@@ -382,11 +390,19 @@ static void red_channel_client_on_output(void *opaque, int n) - { - RedChannelClient *rcc = opaque; - -+ if (rcc->connectivity_monitor.timer) { -+ rcc->connectivity_monitor.out_bytes += n; -+ } - stat_inc_counter(rcc->channel->out_bytes_counter, n); - } - - static void red_channel_client_on_input(void *opaque, int n) - { -+ RedChannelClient *rcc = opaque; -+ -+ if (rcc->connectivity_monitor.timer) { -+ rcc->connectivity_monitor.in_bytes += n; -+ } - } - - static void red_channel_client_default_peer_on_error(RedChannelClient *rcc) -@@ -743,6 +759,97 @@ static void red_channel_client_ping_timer(void *opaque) - } - } - -+/* -+ * When a connection is not alive (and we can't detect it via a socket error), we -+ * reach one of these 2 states: -+ * (1) Sending msgs is blocked: either writes return EAGAIN -+ * or we are missing MSGC_ACK from the client. -+ * (2) MSG_PING was sent without receiving a MSGC_PONG in reply. -+ * -+ * The connectivity_timer callback tests if the channel's state matches one of the above. -+ * In case it does, on the next time the timer is called, it checks if the connection has -+ * been idle during the time that passed since the previous timer call. If the connection -+ * has been idle, we consider the client as disconnected. -+ */ -+static void red_channel_client_connectivity_timer(void *opaque) -+{ -+ RedChannelClient *rcc = opaque; -+ RedChannelClientConnectivityMonitor *monitor = &rcc->connectivity_monitor; -+ int is_alive = TRUE; -+ -+ if (monitor->state == CONNECTIVITY_STATE_BLOCKED) { -+ if (monitor->in_bytes == 0 && monitor->out_bytes == 0) { -+ if (!rcc->send_data.blocked && !red_channel_client_waiting_for_ack(rcc)) { -+ spice_error("mismatch between rcc-state and connectivity-state"); -+ } -+ spice_debug("rcc is blocked; connection is idle"); -+ is_alive = FALSE; -+ } -+ } else if (monitor->state == CONNECTIVITY_STATE_WAIT_PONG) { -+ if (monitor->in_bytes == 0) { -+ if (rcc->latency_monitor.state != PING_STATE_WARMUP && -+ rcc->latency_monitor.state != PING_STATE_LATENCY) { -+ spice_error("mismatch between rcc-state and connectivity-state"); -+ } -+ spice_debug("rcc waits for pong; connection is idle"); -+ is_alive = FALSE; -+ } -+ } -+ -+ if (is_alive) { -+ monitor->in_bytes = 0; -+ monitor->out_bytes = 0; -+ if (rcc->send_data.blocked || red_channel_client_waiting_for_ack(rcc)) { -+ monitor->state = CONNECTIVITY_STATE_BLOCKED; -+ } else if (rcc->latency_monitor.state == PING_STATE_WARMUP || -+ rcc->latency_monitor.state == PING_STATE_LATENCY) { -+ monitor->state = CONNECTIVITY_STATE_WAIT_PONG; -+ } else { -+ monitor->state = CONNECTIVITY_STATE_CONNECTED; -+ } -+ rcc->channel->core->timer_start(rcc->connectivity_monitor.timer, -+ rcc->connectivity_monitor.timeout); -+ } else { -+ monitor->state = CONNECTIVITY_STATE_DISCONNECTED; -+ spice_debug("rcc %p has not been responsive for more than %u ms, disconnecting", -+ rcc, monitor->timeout); -+ red_channel_client_disconnect(rcc); -+ } -+} -+ -+void red_channel_client_start_connectivity_monitoring(RedChannelClient *rcc, uint32_t timeout_ms) -+{ -+ if (!red_channel_client_is_connected(rcc)) { -+ return; -+ } -+ spice_debug(NULL); -+ spice_assert(timeout_ms > 0); -+ /* -+ * If latency_monitor is not active, we activate it in order to enable -+ * periodic ping messages so that we will be be able to identify a disconnected -+ * channel-client even if there are no ongoing channel specific messages -+ * on this channel. -+ */ -+ if (rcc->latency_monitor.timer == NULL) { -+ rcc->latency_monitor.timer = rcc->channel->core->timer_add( -+ red_channel_client_ping_timer, rcc); -+ if (!rcc->client->during_target_migrate) { -+ red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS); -+ } -+ rcc->latency_monitor.roundtrip = -1; -+ } -+ if (rcc->connectivity_monitor.timer == NULL) { -+ rcc->connectivity_monitor.state = CONNECTIVITY_STATE_CONNECTED; -+ rcc->connectivity_monitor.timer = rcc->channel->core->timer_add( -+ red_channel_client_connectivity_timer, rcc); -+ rcc->connectivity_monitor.timeout = timeout_ms; -+ if (!rcc->client->during_target_migrate) { -+ rcc->channel->core->timer_start(rcc->connectivity_monitor.timer, -+ rcc->connectivity_monitor.timeout); -+ } -+ } -+} -+ - RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedClient *client, - RedsStream *stream, - int monitor_latency, -@@ -843,6 +950,10 @@ static void red_channel_client_seamless_migration_done(RedChannelClient *rcc) - if (rcc->latency_monitor.timer) { - red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS); - } -+ if (rcc->connectivity_monitor.timer) { -+ rcc->channel->core->timer_start(rcc->connectivity_monitor.timer, -+ rcc->connectivity_monitor.timeout); -+ } - } - pthread_mutex_unlock(&rcc->client->lock); - } -@@ -889,6 +1000,10 @@ void red_channel_client_default_migrate(RedChannelClient *rcc) - rcc->channel->core->timer_remove(rcc->latency_monitor.timer); - rcc->latency_monitor.timer = NULL; - } -+ if (rcc->connectivity_monitor.timer) { -+ rcc->channel->core->timer_remove(rcc->connectivity_monitor.timer); -+ rcc->connectivity_monitor.timer = NULL; -+ } - red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_MIGRATE); - } - -@@ -1736,6 +1851,10 @@ void red_channel_client_disconnect(RedChannelClient *rcc) - rcc->channel->core->timer_remove(rcc->latency_monitor.timer); - rcc->latency_monitor.timer = NULL; - } -+ if (rcc->connectivity_monitor.timer) { -+ rcc->channel->core->timer_remove(rcc->connectivity_monitor.timer); -+ rcc->connectivity_monitor.timer = NULL; -+ } - red_channel_remove_client(rcc); - rcc->channel->channel_cbs.on_disconnect(rcc); - } -diff --git a/server/red_channel.h b/server/red_channel.h -index 64befff..9e54dce 100644 ---- a/server/red_channel.h -+++ b/server/red_channel.h -@@ -236,6 +236,14 @@ typedef struct RedChannelClientLatencyMonitor { - int64_t roundtrip; - } RedChannelClientLatencyMonitor; - -+typedef struct RedChannelClientConnectivityMonitor { -+ int state; -+ uint32_t out_bytes; -+ uint32_t in_bytes; -+ uint32_t timeout; -+ SpiceTimer *timer; -+} RedChannelClientConnectivityMonitor; -+ - struct RedChannelClient { - RingItem channel_link; - RingItem client_link; -@@ -289,6 +297,7 @@ struct RedChannelClient { - int wait_migrate_flush_mark; - - RedChannelClientLatencyMonitor latency_monitor; -+ RedChannelClientConnectivityMonitor connectivity_monitor; - }; - - struct RedChannel { -@@ -448,6 +457,11 @@ SpiceMarshaller *red_channel_client_switch_to_urgent_sender(RedChannelClient *rc - /* returns -1 if we don't have an estimation */ - int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc); - -+/* -+ * Checks periodically if the connection is still alive -+ */ -+void red_channel_client_start_connectivity_monitoring(RedChannelClient *rcc, uint32_t timeout_ms); -+ - void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type); - - // TODO: add back the channel_pipe_add functionality - by adding reference counting diff --git a/SOURCES/0019-main_channel-monitoring-client-connection-status.patch b/SOURCES/0019-main_channel-monitoring-client-connection-status.patch deleted file mode 100644 index 7f1b99c..0000000 --- a/SOURCES/0019-main_channel-monitoring-client-connection-status.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yonit Halperin -Date: Wed, 14 Aug 2013 10:56:44 -0400 -Subject: [PATCH] main_channel: monitoring client connection status - -rhbz#994175 - -Start monitoring if the client connection is alive after completing -the bit-rate test. - -https://bugzilla.redhat.com/show_bug.cgi?id=1016790 -(cherry picked from commit ed1f70c6d16ff55adf73a08f063f5d7955f4c488) ---- - server/main_channel.c | 27 +++++++++++++++++++++------ - server/main_channel.h | 2 +- - server/reds.c | 3 +-- - 3 files changed, 23 insertions(+), 9 deletions(-) - -diff --git a/server/main_channel.c b/server/main_channel.c -index fe032a6..54718ba 100644 ---- a/server/main_channel.c -+++ b/server/main_channel.c -@@ -55,6 +55,8 @@ - - #define PING_INTERVAL (1000 * 10) - -+#define CLIENT_CONNECTIVITY_TIMEOUT (30*1000) // 30 seconds -+ - static uint8_t zero_page[ZERO_BUF_SIZE] = {0}; - - enum { -@@ -201,16 +203,20 @@ RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t c - - static int main_channel_client_push_ping(MainChannelClient *mcc, int size); - --void main_channel_client_start_net_test(MainChannelClient *mcc) -+void main_channel_client_start_net_test(MainChannelClient *mcc, int test_rate) - { - if (!mcc || mcc->net_test_id) { - return; - } -- if (main_channel_client_push_ping(mcc, NET_TEST_WARMUP_BYTES) -- && main_channel_client_push_ping(mcc, 0) -- && main_channel_client_push_ping(mcc, NET_TEST_BYTES)) { -- mcc->net_test_id = mcc->ping_id - 2; -- mcc->net_test_stage = NET_TEST_STAGE_WARMUP; -+ if (test_rate) { -+ if (main_channel_client_push_ping(mcc, NET_TEST_WARMUP_BYTES) -+ && main_channel_client_push_ping(mcc, 0) -+ && main_channel_client_push_ping(mcc, NET_TEST_BYTES)) { -+ mcc->net_test_id = mcc->ping_id - 2; -+ mcc->net_test_stage = NET_TEST_STAGE_WARMUP; -+ } -+ } else { -+ red_channel_client_start_connectivity_monitoring(&mcc->base, CLIENT_CONNECTIVITY_TIMEOUT); - } - } - -@@ -970,6 +976,8 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint - spice_printerr("net test: invalid values, latency %" PRIu64 - " roundtrip %" PRIu64 ". assuming high" - "bandwidth", mcc->latency, roundtrip); -+ red_channel_client_start_connectivity_monitoring(&mcc->base, -+ CLIENT_CONNECTIVITY_TIMEOUT); - break; - } - mcc->bitrate_per_sec = (uint64_t)(NET_TEST_BYTES * 8) * 1000000 -@@ -980,6 +988,8 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint - mcc->bitrate_per_sec, - (double)mcc->bitrate_per_sec / 1024 / 1024, - main_channel_client_is_low_bandwidth(mcc) ? " LOW BANDWIDTH" : ""); -+ red_channel_client_start_connectivity_monitoring(&mcc->base, -+ CLIENT_CONNECTIVITY_TIMEOUT); - break; - default: - spice_printerr("invalid net test stage, ping id %d test id %d stage %d", -@@ -989,6 +999,11 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint - mcc->net_test_stage = NET_TEST_STAGE_INVALID; - } - break; -+ } else { -+ /* -+ * channel client monitors the connectivity using ping-pong messages -+ */ -+ red_channel_client_handle_message(rcc, size, type, message); - } - #ifdef RED_STATISTICS - reds_update_stat_value(roundtrip); -diff --git a/server/main_channel.h b/server/main_channel.h -index 27367a4..29eb8d4 100644 ---- a/server/main_channel.h -+++ b/server/main_channel.h -@@ -54,7 +54,7 @@ void main_channel_push_agent_disconnected(MainChannel *main_chan); - void main_channel_client_push_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens); - void main_channel_client_push_agent_data(MainChannelClient *mcc, uint8_t* data, size_t len, - spice_marshaller_item_free_func free_data, void *opaque); --void main_channel_client_start_net_test(MainChannelClient *mcc); -+void main_channel_client_start_net_test(MainChannelClient *mcc, int test_rate); - // TODO: huge. Consider making a reds_* interface for these functions - // and calling from main. - void main_channel_push_init(MainChannelClient *mcc, int display_channels_hint, -diff --git a/server/reds.c b/server/reds.c -index f9f185d..7b7f262 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1718,11 +1718,10 @@ static void reds_handle_main_link(RedLinkInfo *link) - main_channel_push_name(mcc, spice_name); - if (spice_uuid_is_set) - main_channel_push_uuid(mcc, spice_uuid); -- -- main_channel_client_start_net_test(mcc); - } else { - reds_mig_target_client_add(client); - } -+ main_channel_client_start_net_test(mcc, !mig_target); - } - - #define RED_MOUSE_STATE_TO_LOCAL(state) \ diff --git a/SOURCES/0020-Fix-crash-when-clearing-surface-memory.patch b/SOURCES/0020-Fix-crash-when-clearing-surface-memory.patch deleted file mode 100644 index 46e831d..0000000 --- a/SOURCES/0020-Fix-crash-when-clearing-surface-memory.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 6 Aug 2014 18:34:56 +0200 -Subject: [PATCH] Fix crash when clearing surface memory - -The beginning of the surface data needs to be computed correctly if the -stride is negative, otherwise, it should point already to the beginning -of the surface data. This bug seems to exists since 4a208b (0.5.2) - -https://bugzilla.redhat.com/show_bug.cgi?id=1029646 ---- - server/red_worker.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/server/red_worker.c b/server/red_worker.c -index 7a1c2d9..d7962c5 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -9654,7 +9654,11 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui - surface->context.stride = stride; - surface->context.line_0 = line_0; - if (!data_is_valid) { -- memset((char *)line_0 + (int32_t)(stride * (height - 1)), 0, height*abs(stride)); -+ char *data = line_0; -+ if (stride < 0) { -+ data -= abs(stride) * (height - 1); -+ } -+ memset(data, 0, height*abs(stride)); - } - surface->create.info = NULL; - surface->destroy.info = NULL; diff --git a/SOURCES/0021-Fix-assert-in-mjpeg_encoder_adjust_params_to_bit_rat.patch b/SOURCES/0021-Fix-assert-in-mjpeg_encoder_adjust_params_to_bit_rat.patch deleted file mode 100644 index 1fc1729..0000000 --- a/SOURCES/0021-Fix-assert-in-mjpeg_encoder_adjust_params_to_bit_rat.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jonathon Jongsma -Date: Fri, 30 May 2014 13:45:02 -0500 -Subject: [PATCH] Fix assert in mjpeg_encoder_adjust_params_to_bit_rate() - -If mjpeg_encoder_reset_quality() is called with the same quality as currently -set, it will not reset last_enc_size but not reset num_recent_enc_frames, -violating some assumptions in _adjust_params_to_bit_rate(). To avoid aborting -the server, simply return early from this function. - -Resolves: rhbz#1070028 -(cherry picked from commit 284cca2a5ebc98257275585083321a7100fb89b3) ---- - server/mjpeg_encoder.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c -index 04b244e..223fe64 100644 ---- a/server/mjpeg_encoder.c -+++ b/server/mjpeg_encoder.c -@@ -624,7 +624,10 @@ static void mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder) - return; - } - -- spice_assert(rate_control->num_recent_enc_frames); -+ if (!rate_control->num_recent_enc_frames) { -+ spice_debug("No recent encoded frames"); -+ return; -+ } - - if (rate_control->num_recent_enc_frames < MJPEG_AVERAGE_SIZE_WINDOW && - rate_control->num_recent_enc_frames < rate_control->fps) { diff --git a/SOURCES/0022-reds-lookup-corresponding-channel-id.patch b/SOURCES/0022-reds-lookup-corresponding-channel-id.patch deleted file mode 100644 index 723acbe..0000000 --- a/SOURCES/0022-reds-lookup-corresponding-channel-id.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Mon, 18 Nov 2013 11:28:25 +0100 -Subject: [PATCH] reds: lookup corresponding channel id - -In reds_send_link_ack(), lookup the channel with the same id as the link -message. - -The bug was found during code review a while ago. - -A reproducer bug was later reported: -https://bugzilla.redhat.com/show_bug.cgi?id=1058625 - -(cherry picked from commit a434543eb1243db1e52ca6a4e0cdfb425c277e56) ---- - server/reds.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/server/reds.c b/server/reds.c -index 7b7f262..464552a 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1459,7 +1459,8 @@ static int reds_send_link_ack(RedLinkInfo *link) - - ack.error = SPICE_LINK_ERR_OK; - -- channel = reds_find_channel(link->link_mess->channel_type, 0); -+ channel = reds_find_channel(link->link_mess->channel_type, -+ link->link_mess->channel_id); - if (!channel) { - spice_assert(link->link_mess->channel_type == SPICE_CHANNEL_MAIN); - spice_assert(reds->main_channel); diff --git a/SOURCES/0023-dispatcher-lower-a-monitor-config-warning-to-a-debug.patch b/SOURCES/0023-dispatcher-lower-a-monitor-config-warning-to-a-debug.patch deleted file mode 100644 index 39f7288..0000000 --- a/SOURCES/0023-dispatcher-lower-a-monitor-config-warning-to-a-debug.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 29 Aug 2014 13:14:08 +0200 -Subject: [PATCH] dispatcher: lower a monitor-config warning to a debug level - -Some QXLInterface implementations might not have or succeed -with client_monitors_config(). Thus, lower warning to debug -level. - -https://bugzilla.redhat.com/show_bug.cgi?id=1119220 -(cherry picked from commit 5972452b287a7b1831411595896e69db2ea991ac) ---- - server/red_dispatcher.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c -index ef47c28..2ebde63 100644 ---- a/server/red_dispatcher.c -+++ b/server/red_dispatcher.c -@@ -330,8 +330,8 @@ void red_dispatcher_client_monitors_config(VDAgentMonitorsConfig *monitors_confi - if (!now->qxl->st->qif->client_monitors_config || - !now->qxl->st->qif->client_monitors_config(now->qxl, - monitors_config)) { -- spice_warning("spice bug: QXLInterface::client_monitors_config" -- " failed/missing unexpectedly\n"); -+ /* this is a normal condition, some qemu devices might not implement it */ -+ spice_debug("QXLInterface::client_monitors_config failed\n"); - } - now = now->next; - } diff --git a/SOURCES/0024-mjpeg-Don-t-warn-on-unsupported-image-formats.patch b/SOURCES/0024-mjpeg-Don-t-warn-on-unsupported-image-formats.patch deleted file mode 100644 index e77bf6e..0000000 --- a/SOURCES/0024-mjpeg-Don-t-warn-on-unsupported-image-formats.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 26 Feb 2014 15:40:55 +0100 -Subject: [PATCH] mjpeg: Don't warn on unsupported image formats - -When trying to start mjpeg compression mode, mjpeg_encoder_start_frame() -tests the image format as its only able to compress 24/32bpp images. On -images with lower bit depths, we return MJPEG_ENCODER_FRAME_UNSUPPORTED to -indicate this is not a format we can compress. However, this return goes -with a spice_warning("unsupported format"). As the rest of the code can -cope with this unsupported format by not doing mjpeg compression, it's -nicer to downgrade this spice_warning() to spice_debug(). - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1070028 - -(cherry picked from commit 67be56ad8a6b10a5307939a700115d6be3fb8433) ---- - server/mjpeg_encoder.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c -index 223fe64..ea9f3af 100644 ---- a/server/mjpeg_encoder.c -+++ b/server/mjpeg_encoder.c -@@ -799,7 +799,7 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format, - #endif - break; - default: -- spice_warning("unsupported format %d", format); -+ spice_debug("unsupported format %d", format); - return MJPEG_ENCODER_FRAME_UNSUPPORTED; - } - diff --git a/SOURCES/0025-server-Don-t-dump-the-bitmap-when-the-format-is-inva.patch b/SOURCES/0025-server-Don-t-dump-the-bitmap-when-the-format-is-inva.patch deleted file mode 100644 index e3ee4f5..0000000 --- a/SOURCES/0025-server-Don-t-dump-the-bitmap-when-the-format-is-inva.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 00:38:36 +0200 -Subject: [PATCH] server: Don't dump the bitmap when the format is invalid - -Caught by covscan: -spice/server/spice_bitmap_utils.c:54: var_decl: Declaring variable "n_pixel_bits" without initializer. -spice/server/spice_bitmap_utils.c:106: uninit_use: Using uninitialized value "n_pixel_bits". - -Resolves: rhbz#885717 -(cherry picked from commit 94edda22553ba351c869b58cd984a79cfc6c2180) ---- - server/red_worker.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/server/red_worker.c b/server/red_worker.c -index d7962c5..945f4f1 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -12296,6 +12296,7 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i - break; - default: - spice_error("invalid bitmap format %u", bitmap->format); -+ return; - } - - if (!rgb) { diff --git a/SOURCES/0026-Fix-Wunused-parameter.patch b/SOURCES/0026-Fix-Wunused-parameter.patch deleted file mode 100644 index 0cb1219..0000000 --- a/SOURCES/0026-Fix-Wunused-parameter.patch +++ /dev/null @@ -1,327 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:24:55 +0200 -Subject: [PATCH] Fix -Wunused-parameter - -(cherry picked from commit 5ea7de3bccafa21963548abcb5b7061de4c59910) ---- - server/tests/test_display_base.c | 37 +++++++++++++++++--------- - server/tests/test_display_base.h | 1 + - server/tests/test_display_no_ssl.c | 2 +- - server/tests/test_display_resolution_changes.c | 3 ++- - server/tests/test_display_width_stride.c | 9 ++++--- - server/tests/test_empty_success.c | 24 +++++++++++------ - server/tests/test_playback.c | 2 +- - server/tests/test_vdagent.c | 13 ++++++--- - 8 files changed, 60 insertions(+), 31 deletions(-) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index 20c0e47..602691b 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -64,7 +64,7 @@ static int rects = 16; //number of rects that will be draw - static int has_automated_tests = 0; //automated test flag - - __attribute__((noreturn)) --static void sigchld_handler(int signal_num) // wait for the child process and exit -+static void sigchld_handler(SPICE_GNUC_UNUSED int signal_num) // wait for the child process and exit - { - int status; - wait(&status); -@@ -412,19 +412,22 @@ static void attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker) - test->qxl_worker->start(test->qxl_worker); - } - --static void set_compression_level(QXLInstance *qin, int level) -+static void set_compression_level(SPICE_GNUC_UNUSED QXLInstance *qin, -+ SPICE_GNUC_UNUSED int level) - { - printf("%s\n", __func__); - } - --static void set_mm_time(QXLInstance *qin, uint32_t mm_time) -+static void set_mm_time(SPICE_GNUC_UNUSED QXLInstance *qin, -+ SPICE_GNUC_UNUSED uint32_t mm_time) - { - } - - // we now have a secondary surface - #define MAX_SURFACE_NUM 2 - --static void get_init_info(QXLInstance *qin, QXLDevInitInfo *info) -+static void get_init_info(SPICE_GNUC_UNUSED QXLInstance *qin, -+ QXLDevInitInfo *info) - { - memset(info, 0, sizeof(*info)); - info->num_memslots = 1; -@@ -467,7 +470,8 @@ static int get_num_commands(void) - } - - // called from spice_server thread (i.e. red_worker thread) --static int get_command(QXLInstance *qin, struct QXLCommandExt *ext) -+static int get_command(SPICE_GNUC_UNUSED QXLInstance *qin, -+ struct QXLCommandExt *ext) - { - if (get_num_commands() == 0) { - return FALSE; -@@ -617,7 +621,8 @@ static void do_wakeup(void *opaque) - test->qxl_worker->wakeup(test->qxl_worker); - } - --static void release_resource(QXLInstance *qin, struct QXLReleaseInfoExt release_info) -+static void release_resource(SPICE_GNUC_UNUSED QXLInstance *qin, -+ struct QXLReleaseInfoExt release_info) - { - QXLCommandExt *ext = (QXLCommandExt*)(unsigned long)release_info.info->id; - //printf("%s\n", __func__); -@@ -713,24 +718,25 @@ static int get_cursor_command(QXLInstance *qin, struct QXLCommandExt *ext) - return TRUE; - } - --static int req_cursor_notification(QXLInstance *qin) -+static int req_cursor_notification(SPICE_GNUC_UNUSED QXLInstance *qin) - { - printf("%s\n", __func__); - return TRUE; - } - --static void notify_update(QXLInstance *qin, uint32_t update_id) -+static void notify_update(SPICE_GNUC_UNUSED QXLInstance *qin, -+ SPICE_GNUC_UNUSED uint32_t update_id) - { - printf("%s\n", __func__); - } - --static int flush_resources(QXLInstance *qin) -+static int flush_resources(SPICE_GNUC_UNUSED QXLInstance *qin) - { - printf("%s\n", __func__); - return TRUE; - } - --static int client_monitors_config(QXLInstance *qin, -+static int client_monitors_config(SPICE_GNUC_UNUSED QXLInstance *qin, - VDAgentMonitorsConfig *monitors_config) - { - if (!monitors_config) { -@@ -786,19 +792,24 @@ void test_add_display_interface(Test* test) - spice_server_add_interface(test->server, &test->qxl_instance.base); - } - --static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -+static int vmc_write(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ SPICE_GNUC_UNUSED const uint8_t *buf, -+ int len) - { - printf("%s: %d\n", __func__, len); - return len; - } - --static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) -+static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ SPICE_GNUC_UNUSED uint8_t *buf, -+ int len) - { - printf("%s: %d\n", __func__, len); - return 0; - } - --static void vmc_state(SpiceCharDeviceInstance *sin, int connected) -+static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ int connected) - { - printf("%s: %d\n", __func__, connected); - } -diff --git a/server/tests/test_display_base.h b/server/tests/test_display_base.h -index d2823a7..0a58186 100644 ---- a/server/tests/test_display_base.h -+++ b/server/tests/test_display_base.h -@@ -2,6 +2,7 @@ - #define __TEST_DISPLAY_BASE_H__ - - #include -+#include - #include "basic_event_loop.h" - - #define COUNT(x) ((sizeof(x)/sizeof(x[0]))) -diff --git a/server/tests/test_display_no_ssl.c b/server/tests/test_display_no_ssl.c -index 83ab3dc..89b4796 100644 ---- a/server/tests/test_display_no_ssl.c -+++ b/server/tests/test_display_no_ssl.c -@@ -17,7 +17,7 @@ void show_channels(SpiceServer *server); - - int ping_ms = 100; - --void pinger(void *opaque) -+void pinger(SPICE_GNUC_UNUSED void *opaque) - { - // show_channels is not thread safe - fails if disconnections / connections occur - //show_channels(server); -diff --git a/server/tests/test_display_resolution_changes.c b/server/tests/test_display_resolution_changes.c -index 4767ea9..c492653 100644 ---- a/server/tests/test_display_resolution_changes.c -+++ b/server/tests/test_display_resolution_changes.c -@@ -22,7 +22,8 @@ void pinger(void *opaque) - test->core->timer_start(ping_timer, ping_ms); - } - --void set_primary_params(Test *test, Command *command) -+void set_primary_params(SPICE_GNUC_UNUSED Test *test, -+ Command *command) - { - #if 0 - static int toggle = 0; -diff --git a/server/tests/test_display_width_stride.c b/server/tests/test_display_width_stride.c -index f938373..a071e74 100644 ---- a/server/tests/test_display_width_stride.c -+++ b/server/tests/test_display_width_stride.c -@@ -25,7 +25,8 @@ void pinger(void *opaque) - static int g_surface_id = 1; - static uint8_t *g_surface_data; - --void set_draw_parameters(Test *test, Command *command) -+void set_draw_parameters(SPICE_GNUC_UNUSED Test *test, -+ Command *command) - { - static int count = 17; - CommandDrawSolid *solid = &command->solid; -@@ -38,7 +39,8 @@ void set_draw_parameters(Test *test, Command *command) - count++; - } - --void set_surface_params(Test *test, Command *command) -+void set_surface_params(SPICE_GNUC_UNUSED Test *test, -+ Command *command) - { - CommandCreateSurface *create = &command->create_surface; - -@@ -54,7 +56,8 @@ void set_surface_params(Test *test, Command *command) - create->data = g_surface_data; - } - --void set_destroy_parameters(Test *test, Command *command) -+void set_destroy_parameters(SPICE_GNUC_UNUSED Test *test, -+ SPICE_GNUC_UNUSED Command *command) - { - if (g_surface_data) { - free(g_surface_data); -diff --git a/server/tests/test_empty_success.c b/server/tests/test_empty_success.c -index 0176a52..6a3bb55 100644 ---- a/server/tests/test_empty_success.c -+++ b/server/tests/test_empty_success.c -@@ -3,44 +3,52 @@ - #include - - #include -+#include - - struct SpiceTimer { - int a,b; - }; - --SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque) -+SpiceTimer* timer_add(SPICE_GNUC_UNUSED SpiceTimerFunc func, -+ SPICE_GNUC_UNUSED void *opaque) - { - static struct SpiceTimer t = {0,}; - - return &t; - } - --void timer_start(SpiceTimer *timer, uint32_t ms) -+void timer_start(SPICE_GNUC_UNUSED SpiceTimer *timer, -+ SPICE_GNUC_UNUSED uint32_t ms) - { - } - --void timer_cancel(SpiceTimer *timer) -+void timer_cancel(SPICE_GNUC_UNUSED SpiceTimer *timer) - { - } - --void timer_remove(SpiceTimer *timer) -+void timer_remove(SPICE_GNUC_UNUSED SpiceTimer *timer) - { - } - --SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque) -+SpiceWatch *watch_add(SPICE_GNUC_UNUSED int fd, -+ SPICE_GNUC_UNUSED int event_mask, -+ SPICE_GNUC_UNUSED SpiceWatchFunc func, -+ SPICE_GNUC_UNUSED void *opaque) - { - return NULL; - } - --void watch_update_mask(SpiceWatch *watch, int event_mask) -+void watch_update_mask(SPICE_GNUC_UNUSED SpiceWatch *watch, -+ SPICE_GNUC_UNUSED int event_mask) - { - } - --void watch_remove(SpiceWatch *watch) -+void watch_remove(SPICE_GNUC_UNUSED SpiceWatch *watch) - { - } - --void channel_event(int event, SpiceChannelEventInfo *info) -+void channel_event(SPICE_GNUC_UNUSED int event, -+ SPICE_GNUC_UNUSED SpiceChannelEventInfo *info) - { - } - -diff --git a/server/tests/test_playback.c b/server/tests/test_playback.c -index ed1b766..1e82c43 100644 ---- a/server/tests/test_playback.c -+++ b/server/tests/test_playback.c -@@ -45,7 +45,7 @@ static void get_frame(void) - : 100; - } - --void playback_timer_cb(void *opaque) -+void playback_timer_cb(SPICE_GNUC_UNUSED void *opaque) - { - static int t = 0; - static uint64_t last_sent_usec = 0; -diff --git a/server/tests/test_vdagent.c b/server/tests/test_vdagent.c -index af33145..7a56c2a 100644 ---- a/server/tests/test_vdagent.c -+++ b/server/tests/test_vdagent.c -@@ -20,7 +20,7 @@ int ping_ms = 100; - #define MIN(a, b) ((a) > (b) ? (b) : (a)) - #endif - --void pinger(void *opaque) -+void pinger(SPICE_GNUC_UNUSED void *opaque) - { - // show_channels is not thread safe - fails if disconnections / connections occur - //show_channels(server); -@@ -29,12 +29,16 @@ void pinger(void *opaque) - } - - --static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -+static int vmc_write(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ SPICE_GNUC_UNUSED const uint8_t *buf, -+ int len) - { - return len; - } - --static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) -+static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ uint8_t *buf, -+ int len) - { - static uint8_t c = 0; - static uint8_t message[2048]; -@@ -70,7 +74,8 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - return ret; - } - --static void vmc_state(SpiceCharDeviceInstance *sin, int connected) -+static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -+ SPICE_GNUC_UNUSED int connected) - { - } - diff --git a/SOURCES/0027-Fix-Wunused-value.patch b/SOURCES/0027-Fix-Wunused-value.patch deleted file mode 100644 index 5298f6b..0000000 --- a/SOURCES/0027-Fix-Wunused-value.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:34:42 +0200 -Subject: [PATCH] Fix -Wunused-value - -(cherry picked from commit 79e5a52d0553b07c0e8ca5a894c5d371a07a8964) ---- - server/tests/test_display_streaming.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/server/tests/test_display_streaming.c b/server/tests/test_display_streaming.c -index b66d870..b8bdf52 100644 ---- a/server/tests/test_display_streaming.c -+++ b/server/tests/test_display_streaming.c -@@ -103,7 +103,7 @@ static void create_clipped_frame(Test *test, Command *command, int clipping_fact - cmd->bitmap = malloc(width*height*4); - memset(cmd->bitmap, 0xff, width*height*4); - dst = (uint32_t *)(cmd->bitmap + cur_line*width*4); -- for (cur_line; cur_line < end_line; cur_line++) { -+ for (; cur_line < end_line; cur_line++) { - int col; - for (col = 0; col < width; col++, dst++) { - *dst = 0x00FF00; diff --git a/SOURCES/0028-Fix-Wsign.patch b/SOURCES/0028-Fix-Wsign.patch deleted file mode 100644 index 0321ae5..0000000 --- a/SOURCES/0028-Fix-Wsign.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:42:48 +0200 -Subject: [PATCH] Fix -Wsign - -(cherry picked from commit 08b3e1d8f187fb371d9ade2f69670378e3e409f5) ---- - server/tests/test_display_base.c | 4 ++-- - server/tests/test_playback.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index 602691b..6765a07 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -215,7 +215,7 @@ static SimpleSpiceUpdate *test_spice_create_update_solid(uint32_t surface_id, QX - uint32_t *dst; - uint32_t bw; - uint32_t bh; -- int i; -+ uint32_t i; - - bw = bbox.right - bbox.left; - bh = bbox.bottom - bbox.top; -@@ -451,7 +451,7 @@ struct QXLCommandExt* commands[1024]; - - static void push_command(QXLCommandExt *ext) - { -- ASSERT(commands_end - commands_start < COMMANDS_SIZE); -+ ASSERT(commands_end - commands_start < (int) COMMANDS_SIZE); - commands[commands_end % COMMANDS_SIZE] = ext; - commands_end++; - } -diff --git a/server/tests/test_playback.c b/server/tests/test_playback.c -index 1e82c43..f712f7b 100644 ---- a/server/tests/test_playback.c -+++ b/server/tests/test_playback.c -@@ -50,7 +50,7 @@ void playback_timer_cb(SPICE_GNUC_UNUSED void *opaque) - static int t = 0; - static uint64_t last_sent_usec = 0; - static uint64_t samples_to_send; -- int i; -+ uint32_t i; - struct timeval cur; - uint64_t cur_usec; - uint32_t *test_frame; diff --git a/SOURCES/0029-Fix-Wswitch.patch b/SOURCES/0029-Fix-Wswitch.patch deleted file mode 100644 index 1923558..0000000 --- a/SOURCES/0029-Fix-Wswitch.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:45:49 +0200 -Subject: [PATCH] Fix -Wswitch - -(cherry picked from commit 4bf5fd35c4ece8a9100e5cec18b4b75fbaf82d35) ---- - server/tests/test_display_base.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index 6765a07..1125b56 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -552,6 +552,8 @@ static void produce_command(Test *test) - update = test_spice_create_update_solid(command->solid.surface_id, - command->solid.bbox, command->solid.color); - break; -+ default: /* Just to shut up GCC warning (-Wswitch) */ -+ break; - } - push_command(&update->ext); - break; diff --git a/SOURCES/0030-Fix-Wformat.patch b/SOURCES/0030-Fix-Wformat.patch deleted file mode 100644 index fa19f08..0000000 --- a/SOURCES/0030-Fix-Wformat.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:52:16 +0200 -Subject: [PATCH] Fix -Wformat - -(cherry picked from commit 63180f6ce3266d3b9b6c7319a0aec1f0d4ee7fe3) ---- - server/tests/basic_event_loop.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/server/tests/basic_event_loop.c b/server/tests/basic_event_loop.c -index c6f6698..79a4523 100644 ---- a/server/tests/basic_event_loop.c -+++ b/server/tests/basic_event_loop.c -@@ -115,7 +115,7 @@ static void watch_remove(SpiceWatch *watch) - - static void channel_event(int event, SpiceChannelEventInfo *info) - { -- DPRINTF(0, "channel event con, type, id, event: %ld, %d, %d, %d", -+ DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d", - info->connection_id, info->type, info->id, event); - } - diff --git a/SOURCES/0031-Fix-Wnonnull.patch b/SOURCES/0031-Fix-Wnonnull.patch deleted file mode 100644 index 3ed5ae3..0000000 --- a/SOURCES/0031-Fix-Wnonnull.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 13:55:56 +0200 -Subject: [PATCH] Fix -Wnonnull - -(cherry picked from commit fb938c210ac507acb747c4c5126db7e6b12889fa) ---- - server/tests/test_display_base.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index 1125b56..01eaf9f 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -88,10 +88,11 @@ static void regression_test(void) - pid = fork(); - if (pid == 0) { - char buf[PATH_MAX]; -+ char *argv[] = { NULL }; - char *envp[] = {buf, NULL}; - - snprintf(buf, sizeof(buf), "PATH=%s", getenv("PATH")); -- execve("regression_test.py", NULL, envp); -+ execve("regression_test.py", argv, envp); - } else if (pid > 0) { - return; - } diff --git a/SOURCES/0032-Fix-Wmissing-field-initializers.patch b/SOURCES/0032-Fix-Wmissing-field-initializers.patch deleted file mode 100644 index d96b117..0000000 --- a/SOURCES/0032-Fix-Wmissing-field-initializers.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 14:19:52 +0200 -Subject: [PATCH] Fix -Wmissing-field-initializers - -(cherry picked from commit b76e561d82796bd2bccc57be962fc5fba0141da6) ---- - server/tests/test_display_base.c | 15 ++++++--------- - server/tests/test_display_resolution_changes.c | 4 ++-- - server/tests/test_display_width_stride.c | 22 +++++++++++----------- - server/tests/test_playback.c | 12 ++++++------ - server/tests/test_vdagent.c | 15 ++++++--------- - 5 files changed, 31 insertions(+), 37 deletions(-) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index 01eaf9f..bfe9991 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -817,19 +817,16 @@ static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, - printf("%s: %d\n", __func__, connected); - } - --static SpiceCharDeviceInterface vdagent_sif = { -- .base.type = SPICE_INTERFACE_CHAR_DEVICE, -- .base.description = "test spice virtual channel char device", -- .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, -- .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, -- .state = vmc_state, -- .write = vmc_write, -- .read = vmc_read, -+static SpiceBaseInterface base = { -+ .type = SPICE_INTERFACE_CHAR_DEVICE, -+ .description = "test spice virtual channel char device", -+ .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, -+ .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, - }; - - SpiceCharDeviceInstance vdagent_sin = { - .base = { -- .sif = &vdagent_sif.base, -+ .sif = &base, - }, - .subtype = "vdagent", - }; -diff --git a/server/tests/test_display_resolution_changes.c b/server/tests/test_display_resolution_changes.c -index c492653..e351e99 100644 ---- a/server/tests/test_display_resolution_changes.c -+++ b/server/tests/test_display_resolution_changes.c -@@ -45,8 +45,8 @@ void set_primary_params(SPICE_GNUC_UNUSED Test *test, - } - - static Command commands[] = { -- {DESTROY_PRIMARY, NULL}, -- {CREATE_PRIMARY, set_primary_params}, -+ {DESTROY_PRIMARY, NULL, .cb_opaque = NULL,}, -+ {CREATE_PRIMARY, set_primary_params, .cb_opaque = NULL}, - }; - - int main(void) -diff --git a/server/tests/test_display_width_stride.c b/server/tests/test_display_width_stride.c -index a071e74..77d3c12 100644 ---- a/server/tests/test_display_width_stride.c -+++ b/server/tests/test_display_width_stride.c -@@ -66,17 +66,17 @@ void set_destroy_parameters(SPICE_GNUC_UNUSED Test *test, - } - - static Command commands[] = { -- {SIMPLE_CREATE_SURFACE, set_surface_params}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DRAW_SOLID, set_draw_parameters}, -- {SIMPLE_DESTROY_SURFACE, set_destroy_parameters}, -+ {SIMPLE_CREATE_SURFACE, set_surface_params, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL}, -+ {SIMPLE_DESTROY_SURFACE, set_destroy_parameters, .cb_opaque = NULL}, - }; - - void on_client_connected(Test *test) -diff --git a/server/tests/test_playback.c b/server/tests/test_playback.c -index f712f7b..a6c3d7e 100644 ---- a/server/tests/test_playback.c -+++ b/server/tests/test_playback.c -@@ -21,11 +21,11 @@ - - SpicePlaybackInstance playback_instance; - --static const SpicePlaybackInterface playback_sif = { -- .base.type = SPICE_INTERFACE_PLAYBACK, -- .base.description = "test playback", -- .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR, -- .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR, -+static const SpiceBaseInterface base = { -+ .type = SPICE_INTERFACE_PLAYBACK, -+ .description = "test playback", -+ .major_version = SPICE_INTERFACE_PLAYBACK_MAJOR, -+ .minor_version = SPICE_INTERFACE_PLAYBACK_MINOR, - }; - - uint32_t *frame; -@@ -99,7 +99,7 @@ int main(void) - spice_server_set_noauth(server); - spice_server_init(server, core); - -- playback_instance.base.sif = &playback_sif.base; -+ playback_instance.base.sif = &base; - spice_server_add_interface(server, &playback_instance.base); - spice_server_playback_start(&playback_instance); - -diff --git a/server/tests/test_vdagent.c b/server/tests/test_vdagent.c -index 7a56c2a..191ad05 100644 ---- a/server/tests/test_vdagent.c -+++ b/server/tests/test_vdagent.c -@@ -79,14 +79,11 @@ static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, - { - } - --static SpiceCharDeviceInterface vmc_interface = { -- .base.type = SPICE_INTERFACE_CHAR_DEVICE, -- .base.description = "test spice virtual channel char device", -- .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, -- .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, -- .state = vmc_state, -- .write = vmc_write, -- .read = vmc_read, -+static SpiceBaseInterface base = { -+ .type = SPICE_INTERFACE_CHAR_DEVICE, -+ .description = "test spice virtual channel char device", -+ .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, -+ .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, - }; - - SpiceCharDeviceInstance vmc_instance = { -@@ -100,7 +97,7 @@ int main(void) - core = basic_event_loop_init(); - test = test_new(core); - -- vmc_instance.base.sif = &vmc_interface.base; -+ vmc_instance.base.sif = &base; - spice_server_add_interface(test->server, &vmc_instance.base); - - ping_timer = core->timer_add(pinger, NULL); diff --git a/SOURCES/0033-Fix-Wunused-function.patch b/SOURCES/0033-Fix-Wunused-function.patch deleted file mode 100644 index 38d958f..0000000 --- a/SOURCES/0033-Fix-Wunused-function.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 1 Sep 2014 15:06:54 +0200 -Subject: [PATCH] Fix -Wunused-function - -(cherry picked from commit 93b4f4050c57bd851292e4cee884888cee56fc31) ---- - server/tests/test_display_base.c | 22 ----------------- - server/tests/test_vdagent.c | 51 ---------------------------------------- - 2 files changed, 73 deletions(-) - -diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c -index bfe9991..36b4fc1 100644 ---- a/server/tests/test_display_base.c -+++ b/server/tests/test_display_base.c -@@ -795,28 +795,6 @@ void test_add_display_interface(Test* test) - spice_server_add_interface(test->server, &test->qxl_instance.base); - } - --static int vmc_write(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- SPICE_GNUC_UNUSED const uint8_t *buf, -- int len) --{ -- printf("%s: %d\n", __func__, len); -- return len; --} -- --static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- SPICE_GNUC_UNUSED uint8_t *buf, -- int len) --{ -- printf("%s: %d\n", __func__, len); -- return 0; --} -- --static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- int connected) --{ -- printf("%s: %d\n", __func__, connected); --} -- - static SpiceBaseInterface base = { - .type = SPICE_INTERFACE_CHAR_DEVICE, - .description = "test spice virtual channel char device", -diff --git a/server/tests/test_vdagent.c b/server/tests/test_vdagent.c -index 191ad05..22153b6 100644 ---- a/server/tests/test_vdagent.c -+++ b/server/tests/test_vdagent.c -@@ -28,57 +28,6 @@ void pinger(SPICE_GNUC_UNUSED void *opaque) - core->timer_start(ping_timer, ping_ms); - } - -- --static int vmc_write(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- SPICE_GNUC_UNUSED const uint8_t *buf, -- int len) --{ -- return len; --} -- --static int vmc_read(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- uint8_t *buf, -- int len) --{ -- static uint8_t c = 0; -- static uint8_t message[2048]; -- static unsigned pos = 0; -- static unsigned message_size; -- int ret; -- -- if (pos == 0) { -- VDIChunkHeader *hdr = (VDIChunkHeader *)message; -- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1]; -- uint8_t *p = message; -- int size = sizeof(message); -- message_size = size; -- /* fill in message */ -- hdr->port = VDP_SERVER_PORT; -- hdr->size = message_size - sizeof(VDIChunkHeader); -- msg->protocol = VD_AGENT_PROTOCOL; -- msg->type = VD_AGENT_END_MESSAGE; -- msg->opaque = 0; -- msg->size = message_size - sizeof(VDIChunkHeader) - sizeof(VDAgentMessage); -- size -= sizeof(VDIChunkHeader) + sizeof(VDAgentMessage); -- p += sizeof(VDIChunkHeader) + sizeof(VDAgentMessage); -- for (; size; --size, ++p, ++c) -- *p = c; -- } -- ret = MIN(message_size - pos, len); -- memcpy(buf, &message[pos], ret); -- pos += ret; -- if (pos == message_size) { -- pos = 0; -- } -- //printf("vmc_read %d (ret %d)\n", len, ret); -- return ret; --} -- --static void vmc_state(SPICE_GNUC_UNUSED SpiceCharDeviceInstance *sin, -- SPICE_GNUC_UNUSED int connected) --{ --} -- - static SpiceBaseInterface base = { - .type = SPICE_INTERFACE_CHAR_DEVICE, - .description = "test spice virtual channel char device", diff --git a/SOURCES/0034-Validate-surface-bounding-box-before-using-it.patch b/SOURCES/0034-Validate-surface-bounding-box-before-using-it.patch deleted file mode 100644 index 701d618..0000000 --- a/SOURCES/0034-Validate-surface-bounding-box-before-using-it.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Tue, 9 Sep 2014 18:00:30 +0200 -Subject: [PATCH] Validate surface bounding box before using it - -It's possible for a buggy guest driver to pass invalid bounding box -dimensions in QXL commands, which would then cause spice-server to -segfault. This patch checks the size of the bounding box of the QXL -command right after it has been parsed. - -This fixes rhbz#1135372 - -(cherry picked from commit e270edcbfd958d764e84cdbca6d403ff24fef610) ---- - server/red_worker.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - -diff --git a/server/red_worker.c b/server/red_worker.c -index 945f4f1..9e6a6ad 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -1272,6 +1272,33 @@ 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; -+ uint32_t surface_id = drawable->surface_id; -+ -+ /* surface_id must be validated before calling into -+ * validate_drawable_bbox -+ */ -+ __validate_surface(worker, surface_id); -+ context = &worker->surfaces[surface_id].context; -+ -+ if (drawable->bbox.top < 0) -+ return FALSE; -+ if (drawable->bbox.left < 0) -+ return FALSE; -+ if (drawable->bbox.bottom < 0) -+ return FALSE; -+ if (drawable->bbox.right < 0) -+ return FALSE; -+ if (drawable->bbox.bottom > context->height) -+ return FALSE; -+ if (drawable->bbox.right > context->width) -+ return FALSE; -+ -+ return TRUE; -+} -+ - static inline int validate_surface(RedWorker *worker, uint32_t surface_id) - { - spice_warn_if(surface_id >= worker->n_surfaces); -@@ -4117,6 +4144,10 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re - VALIDATE_SURFACE_RETVAL(worker, drawable->surfaces_dest[x], NULL) - } - } -+ if (!validate_drawable_bbox(worker, red_drawable)) { -+ rendering_incorrect(__func__); -+ return NULL; -+ } - ring_init(&drawable->pipes); - ring_init(&drawable->glz_ring); - diff --git a/SOURCES/0035-migration-Don-t-assert-if-MIGRATE_DATA-comes-before-.patch b/SOURCES/0035-migration-Don-t-assert-if-MIGRATE_DATA-comes-before-.patch deleted file mode 100644 index 80167ae..0000000 --- a/SOURCES/0035-migration-Don-t-assert-if-MIGRATE_DATA-comes-before-.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Uri Lublin -Date: Wed, 16 Jul 2014 17:02:04 +0300 -Subject: [PATCH] migration: Don't assert() if MIGRATE_DATA comes before - attaching the agent - -During seamless migration, after switching host, if a client was connected -during the migration, it will have data to send back to the new -qemu/spice-server instance. This is handled through MIGRATE_DATA messages. -SPICE char devices use such MIGRATE_DATA messages to restore their state. - -However, the MIGRATE_DATA message can arrive any time after the new qemu -instance has started, this can happen before or after the SPICE char -devices have been created. In order to handle this, if the migrate data -arrives early, it's stored in reds->agent_state.mig_data, and -attach_to_red_agent() will restore the agent state as appropriate. - -Unfortunately this does not work as expected, for main -channel (agent messages). -If attach_to_red_agent() is called before the MIGRATE_DATA -message reaches the server, all goes well, -but if MIGRATE_DATA reaches the server before -attach_to_red_agent() gets called, then some assert() gets -triggered in spice_char_device_state_restore(): - -((null):32507): Spice-ERROR **: char_device.c:937:spice_char_device_state_restore: assertion `dev->num_clients == 1 && dev->wait_for_migrate_data' failed -Thread 3 (Thread 0x7f406b543700 (LWP 32543)): -Thread 2 (Thread 0x7f40697ff700 (LWP 32586)): -Thread 1 (Thread 0x7f4079b45a40 (LWP 32507)): - -When restoring state, a client must already be added to the -spice-char-device. -What happens is that a client is not being added to the char-device -when when MIGRATE_DATA arrives first, which leaves both -dev->num_clients and dev->wait_for_migrate_data value at 0. - -This commit changes the logic in spice_server_char_device_add_interface(), -such that if there is migrate data pending in reds->agent_state.mig_data -but no client was added to the spice-char-device yet, -then first the client is added to the device by calling -spice_char_device_client_add(), and only then the state is restored. - -=== How to Reproduce -To reproduce, add delays to the migration connection between -qmeu-kvm on the source host (SRC) and on the destination (DST). - -Specifically I added a man in the middle DLY host between -migration ports from SRC to DST. - -+-----+ +-----+ +-----+ -| SRC |--> | DLY | --> | DST | -+-----+ +-----+ +-----+ - -DLY listens on port P1 (e.g. 4444) and DST listens on port -PINCOMING (e.g. 4444, from qemu-kvm '-incoming' command line option) - -Precondition: make sure port P1 on DLY is accessible in iptables. -Option 1: use ssh tcp port forwarding -On DLY host run ssh: - ssh DLY:P1:DST:PINCOMING DST -Then use the following migration command (on qemu-kvm monitor): - client_migrate_info spice DST PSPICE - migrate -d tcp:DLY:P1 - -Option 2: Use a simple proxy program that forwards -packets from SRC to DST while adding some delays. -The program runs on DLY, listens to port D1, upon -accept connects to DST:PINCOMING and forward all -packets from DLY:D1 to DST:PINCOMING. -Then use the same migrate command as in option 1: - client_migrate_info spice DST PSPICE - migrate -d tcp:DLY:P1 - -=== How to Reproduce Ends - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1035184 - -Based-on-a-patch-by: Christophe Fergeau -(cherry picked from commit 2d1c00a659cd1b3998f5d1f90fc5ee6abb7519bb) ---- - server/reds.c | 39 ++++++++++++++++++++++++++++----------- - 1 file changed, 28 insertions(+), 11 deletions(-) - -diff --git a/server/reds.c b/server/reds.c -index 464552a..06e9a3e 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1373,6 +1373,7 @@ int reds_handle_migrate_data(MainChannelClient *mcc, SpiceMigrateDataMain *mig_d - { - VDIPortState *agent_state = &reds->agent_state; - -+ spice_debug("main-channel: got migrate data"); - /* - * Now that the client has switched to the target server, if main_channel - * controls the mm-time, we update the client's mm-time. -@@ -1394,15 +1395,18 @@ int reds_handle_migrate_data(MainChannelClient *mcc, SpiceMigrateDataMain *mig_d - main_channel_push_agent_disconnected(reds->main_channel); - main_channel_push_agent_connected(reds->main_channel); - } else { -+ spice_debug("restoring state from mig_data"); - return reds_agent_state_restore(mig_data); - } - } - } else { - /* restore agent starte when the agent gets attached */ -+ spice_debug("saving mig_data"); - spice_assert(agent_state->plug_generation == 0); - agent_state->mig_data = spice_memdup(mig_data, size); - } - } else { -+ spice_debug("agent was not attached on the source host"); - if (vdagent) { - /* spice_char_device_client_remove disables waiting for migration data */ - spice_char_device_client_remove(agent_state->base, -@@ -3589,17 +3593,15 @@ static SpiceCharDeviceState *attach_to_red_agent(SpiceCharDeviceInstance *sin) - state->read_filter.discard_all = FALSE; - reds->agent_state.plug_generation++; - -- if (reds->agent_state.mig_data) { -- spice_assert(reds->agent_state.plug_generation == 1); -- reds_agent_state_restore(reds->agent_state.mig_data); -- free(reds->agent_state.mig_data); -- reds->agent_state.mig_data = NULL; -- } else if (!red_channel_waits_for_migrate_data(&reds->main_channel->base)) { -- /* we will assoicate the client with the char device, upon reds_on_main_agent_start, -- * in response to MSGC_AGENT_START */ -- main_channel_push_agent_connected(reds->main_channel); -- } else { -- spice_debug("waiting for migration data"); -+ if (reds->agent_state.mig_data || -+ red_channel_waits_for_migrate_data(&reds->main_channel->base)) { -+ /* Migration in progress (code is running on the destination host): -+ * 1. Add the client to spice char device, if it was not already added. -+ * 2.a If this (qemu-kvm state load side of migration) happens first -+ * then wait for spice migration data to arrive. Otherwise -+ * 2.b If this happens second ==> we already have spice migrate data -+ * then restore state -+ */ - if (!spice_char_device_client_exists(reds->agent_state.base, reds_get_client())) { - int client_added; - -@@ -3615,9 +3617,24 @@ static SpiceCharDeviceState *attach_to_red_agent(SpiceCharDeviceInstance *sin) - spice_warning("failed to add client to agent"); - reds_disconnect(); - } -+ } - -+ if (reds->agent_state.mig_data) { -+ spice_debug("restoring state from stored migration data"); -+ spice_assert(reds->agent_state.plug_generation == 1); -+ reds_agent_state_restore(reds->agent_state.mig_data); -+ free(reds->agent_state.mig_data); -+ reds->agent_state.mig_data = NULL; -+ } -+ else { -+ spice_debug("waiting for migration data"); - } -+ } else { -+ /* we will associate the client with the char device, upon reds_on_main_agent_start, -+ * in response to MSGC_AGENT_START */ -+ main_channel_push_agent_connected(reds->main_channel); - } -+ - return state->base; - } - diff --git a/SOURCES/0036-server-fix-crash-when-restarting-VM-with-old-client.patch b/SOURCES/0036-server-fix-crash-when-restarting-VM-with-old-client.patch deleted file mode 100644 index 93a8405..0000000 --- a/SOURCES/0036-server-fix-crash-when-restarting-VM-with-old-client.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Thu, 9 Oct 2014 17:23:06 +0200 -Subject: [PATCH] server: fix crash when restarting VM with old client - -The server will reset the vdagent char device when the client does not -implement SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS. This will nullify -dev->sin and the following crash will be reached on restart: - - #0 0x00007fb05aa264a1 in spice_char_device_write_to_device (dev=dev@entry=0x7fb066ae5d30) at char_device.c:443 - #1 0x00007fb05aa27137 in spice_char_device_write_to_device (dev=0x7fb066ae5d30) at char_device.c:436 - #2 spice_char_device_start (dev=0x7fb066ae5d30) at char_device.c:798 - #3 0x00007fb05aa6a981 in spice_server_vm_start (s=) at reds.c:3795 - #4 0x00007fb0644b7f89 in qdev_reset_one (dev=, opaque=) at hw/core/qdev.c:241 - #5 0x00007fb0644b7918 in qbus_walk_children (bus=0x7fb06661e870, pre_devfn=0x0, pre_busfn=0x0, - post_devfn=0x7fb0644b7f80 , post_busfn=0x7fb0644b6350 , opaque=0x0) - at hw/core/qdev.c:422 - #6 0x00007fb0644b7848 in qdev_walk_children (dev=0x7fb0665f47a0, pre_devfn=0x0, pre_busfn=0x0, - post_devfn=0x7fb0644b7f80 , post_busfn=0x7fb0644b6350 , opaque=0x0) - at hw/core/qdev.c:456 - #7 0x00007fb0644b7918 in qbus_walk_children (bus=0x7fb06647cde0, pre_devfn=0x0, pre_busfn=0x0, - post_devfn=0x7fb0644b7f80 , post_busfn=0x7fb0644b6350 , opaque=0x0) - at hw/core/qdev.c:422 - #8 0x00007fb0644399fd in qemu_devices_reset () at vl.c:1830 - -After restart, qemu will reset the device instance (sin) when virtio -port is opened: - - #0 spice_char_device_state_reset_dev_instance (state=0x7fe4873876d0, sin=sin@entry=0x7fe486fb0c68) - at char_device.c:667 - #1 0x00007fe47b277516 in attach_to_red_agent (sin=0x7fe486fb0c68) at reds.c:2838 - #2 spice_server_char_device_add_interface (sin=0x7fe486fb0c68, s=0x7fe486fb2e60) at reds.c:2962 - #3 spice_server_add_interface (s=0x7fe486fb2e60, sin=0x7fe486fb0c68) at reds.c:3104 - #4 0x00007fe484c69e57 in vmc_register_interface (scd=0x7fe486fb0c60) at spice-qemu-char.c:123 - #5 0x00007fe484ce96b4 in set_guest_connected (port=, guest_connected=1) - at hw/char/virtio-console.c:89 - #6 0x00007fe484ba70ed in handle_control_message (len=8, buf=0x7fe486fbdf70, vser=0x7fe48739ae98) - at /usr/src/debug/qemu-2.1.0/hw/char/virtio-serial-bus.c:382 - -Let's ignore the call to spice_char_device_{write,read}_to_device() when -dev->sin is NULL, similary to other conditions, such as dev->running. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1145919 -(cherry picked from commit 4639817f0eb26316894cc83b43a736bdd72f9018) ---- - server/char_device.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/server/char_device.c b/server/char_device.c -index 660a788..6d2339e 100644 ---- a/server/char_device.c -+++ b/server/char_device.c -@@ -283,7 +283,7 @@ static int spice_char_device_read_from_device(SpiceCharDeviceState *dev) - uint64_t max_send_tokens; - int did_read = FALSE; - -- if (!dev->running || dev->wait_for_migrate_data) { -+ if (!dev->running || dev->wait_for_migrate_data || !dev->sin) { - return FALSE; - } - -@@ -433,7 +433,7 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - int total = 0; - int n; - -- if (!dev->running || dev->wait_for_migrate_data) { -+ if (!dev->running || dev->wait_for_migrate_data || !dev->sin) { - return 0; - } - diff --git a/SOURCES/0037-Use-TLS-version-1.0-or-better.patch b/SOURCES/0037-Use-TLS-version-1.0-or-better.patch deleted file mode 100644 index 310feda..0000000 --- a/SOURCES/0037-Use-TLS-version-1.0-or-better.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?David=20Ja=C5=A1a?= -Date: Wed, 27 Nov 2013 17:45:49 +0100 -Subject: [PATCH] Use TLS version 1.0 or better - -When creating a TLS socket, both spice-server and spice-gtk currently -call SSL_CTX_new(TLSv1_method()). The TLSv1_method() function set the -protocol version to TLS 1.0 exclusively. The correct way to support -multiple protocol versions is to call SSLv23_method() in spite of its -scary name. This method will enable all SSL/TLS protocol versions. The -protocol suite may be further narrowed down by setting respective -SSL_OP_NO_ options of SSL context. This possibility is -used in this patch in order to block use of SSLv3 that is enabled by -default in openssl for client sockets as of now but spice has never used -it. ---- - server/reds.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/server/reds.c b/server/reds.c -index 06e9a3e..ccba67c 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -3232,6 +3232,8 @@ static int reds_init_ssl(void) - SSL_METHOD *ssl_method; - #endif - int return_code; -+ /* When some other SSL/TLS version becomes obsolete, add it to this -+ * variable. */ - long ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - - /* Global system initialization*/ -@@ -3239,7 +3241,8 @@ static int reds_init_ssl(void) - SSL_load_error_strings(); - - /* Create our context*/ -- ssl_method = TLSv1_method(); -+ /* SSLv23_method() handles TLSv1.x in addition to SSLv2/v3 */ -+ ssl_method = SSLv23_method(); - reds->ctx = SSL_CTX_new(ssl_method); - if (!reds->ctx) { - spice_warning("Could not allocate new SSL context"); diff --git a/SOURCES/0038-Add-const-to-test_capability-first-argument.patch b/SOURCES/0038-Add-const-to-test_capability-first-argument.patch deleted file mode 100644 index e7f2de9..0000000 --- a/SOURCES/0038-Add-const-to-test_capability-first-argument.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 19 Mar 2014 18:17:32 +0100 -Subject: [PATCH] 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; diff --git a/SOURCES/0039-Introduce-red_link_info_test_capability.patch b/SOURCES/0039-Introduce-red_link_info_test_capability.patch deleted file mode 100644 index 434663d..0000000 --- a/SOURCES/0039-Introduce-red_link_info_test_capability.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 5 Mar 2014 11:59:37 +0100 -Subject: [PATCH] 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..9971b7a 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) { 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 deleted file mode 100644 index 9c2c90c..0000000 --- a/SOURCES/0040-Don-t-set-SpiceLinkReply-pub_key-if-client-advertise.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Thu, 9 Jul 2015 01:04:31 +0200 -Subject: [PATCH] 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 9971b7a..f996c71 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; - } - 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 deleted file mode 100644 index f920c78..0000000 --- a/SOURCES/0041-server-don-t-assert-on-invalid-client-message.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -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) { 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 deleted file mode 100644 index 1e34305..0000000 --- a/SOURCES/0042-Don-t-truncate-large-now-values-in-_spice_timer_set.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Gibson -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); 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 deleted file mode 100644 index 14ed533..0000000 --- a/SOURCES/0043-Avoid-race-conditions-reading-monitor-configs-from-g.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -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 ---- - 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); - } - 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 deleted file mode 100644 index 2b4c80e..0000000 --- a/SOURCES/0044-Lock-the-pixmap-image-cache-for-the-entire-fill_bits.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandy Stutsman -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; - } - 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 deleted file mode 100644 index 35614e0..0000000 --- a/SOURCES/0045-reds-Assure-we-don-t-have-stale-statistic-files-befo.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -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 ---- - server/reds.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/server/reds.c b/server/reds.c -index f996c71..e96f28d 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -4011,6 +4011,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)); - } diff --git a/SOURCES/0046-worker-validate-correctly-surfaces.patch b/SOURCES/0046-worker-validate-correctly-surfaces.patch deleted file mode 100644 index 4c83112..0000000 --- a/SOURCES/0046-worker-validate-correctly-surfaces.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Wed, 9 Sep 2015 12:42:09 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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); 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 deleted file mode 100644 index 5565ad2..0000000 --- a/SOURCES/0047-worker-avoid-double-free-or-double-create-of-surface.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Wed, 9 Sep 2015 12:45:06 +0100 -Subject: [PATCH] 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 ---- - 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. 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 deleted file mode 100644 index 7ab58f5..0000000 --- a/SOURCES/0048-Define-a-constant-to-limit-data-from-guest.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 11:58:11 +0100 -Subject: [PATCH] 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 ---- - 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 - #include -+#include - #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) 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 deleted file mode 100644 index e03bba2..0000000 --- a/SOURCES/0049-Fix-some-integer-overflow-causing-large-memory-alloc.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Thu, 17 Sep 2015 15:00:22 +0100 -Subject: [PATCH] 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 ---- - 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) { diff --git a/SOURCES/0050-Check-properly-surface-to-be-created.patch b/SOURCES/0050-Check-properly-surface-to-be-created.patch deleted file mode 100644 index 4e5297b..0000000 --- a/SOURCES/0050-Check-properly-surface-to-be-created.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 16:02:59 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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 = diff --git a/SOURCES/0051-Fix-buffer-reading-overflow.patch b/SOURCES/0051-Fix-buffer-reading-overflow.patch deleted file mode 100644 index 4a7a9cc..0000000 --- a/SOURCES/0051-Fix-buffer-reading-overflow.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 10:00:37 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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", 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 deleted file mode 100644 index 5a990ad..0000000 --- a/SOURCES/0052-Prevent-32-bit-integer-overflow-in-bitmap_consistent.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 13:09:35 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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); 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 deleted file mode 100644 index 83ebfe1..0000000 --- a/SOURCES/0053-Fix-race-condition-on-red_get_clip_rects.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 10:01:51 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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++) { diff --git a/SOURCES/0054-Fix-race-in-red_get_image.patch b/SOURCES/0054-Fix-race-in-red_get_image.patch deleted file mode 100644 index fa53795..0000000 --- a/SOURCES/0054-Fix-race-in-red_get_image.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 10:04:10 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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; - } diff --git a/SOURCES/0055-Fix-race-condition-in-red_get_string.patch b/SOURCES/0055-Fix-race-condition-in-red_get_string.patch deleted file mode 100644 index 5e7a716..0000000 --- a/SOURCES/0055-Fix-race-condition-in-red_get_string.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 10:05:20 +0100 -Subject: [PATCH] Fix race condition in red_get_string - -Do not read multiple time an array size that can be changed. - -Signed-off-by: Frediano Ziglio -Acked-by: Christophe Fergeau ---- - 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); 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 deleted file mode 100644 index 34a462f..0000000 --- a/SOURCES/0056-Fix-integer-overflow-computing-glyph_size-in-red_get.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 10:13:24 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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]); 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 deleted file mode 100644 index e17c267..0000000 --- a/SOURCES/0057-Fix-race-condition-in-red_get_data_chunks_ptr.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 12:12:19 +0100 -Subject: [PATCH] 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 ---- - 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; - } 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 deleted file mode 100644 index 34a3f83..0000000 --- a/SOURCES/0058-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 12:14:55 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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, 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 deleted file mode 100644 index 88d955a..0000000 --- a/SOURCES/0059-Prevent-DoS-from-guest-trying-to-allocate-too-much-d.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 12:28:54 +0100 -Subject: [PATCH] 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 ---- - 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; - } 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 deleted file mode 100644 index ca0dff1..0000000 --- a/SOURCES/0060-Fix-some-possible-overflows-in-red_get_string-for-32.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 8 Sep 2015 13:06:03 +0100 -Subject: [PATCH] Fix some possible overflows in red_get_string for 32 bit - -Signed-off-by: Frediano Ziglio -Acked-by: Christophe Fergeau ---- - 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*) diff --git a/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch b/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch deleted file mode 100644 index dd68ace..0000000 --- a/SOURCES/0061-Make-sure-we-can-read-QXLPathSeg-structures.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 15 Sep 2015 16:25:17 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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; - 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 deleted file mode 100644 index c6f4253..0000000 --- a/SOURCES/0062-Avoid-race-condition-copying-segments-in-red_get_pat.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 15 Sep 2015 16:38:23 +0100 -Subject: [PATCH] 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 -Acked-by: Christophe Fergeau ---- - 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; - 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 deleted file mode 100644 index 4cbe23b..0000000 --- a/SOURCES/0063-Prevent-data_size-to-be-set-independently-from-data.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Thu, 17 Sep 2015 14:28:36 +0100 -Subject: [PATCH] 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 ---- - 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) { 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 deleted file mode 100644 index a0bbb61..0000000 --- a/SOURCES/0064-Prevent-leak-if-size-from-red_get_data_chunks-don-t-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Thu, 17 Sep 2015 15:01:05 +0100 -Subject: [PATCH] Prevent leak if size from red_get_data_chunks don't match in - red_get_image - -Signed-off-by: Frediano Ziglio ---- - 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, diff --git a/SOURCES/0065-smartcard-add-a-ref-to-item-before-adding-to-pipe.patch b/SOURCES/0065-smartcard-add-a-ref-to-item-before-adding-to-pipe.patch deleted file mode 100644 index 2d79fbb..0000000 --- a/SOURCES/0065-smartcard-add-a-ref-to-item-before-adding-to-pipe.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Marc-Andre Lureau -Date: Thu, 17 Dec 2015 18:13:47 +0100 -Subject: [PATCH] smartcard: add a ref to item before adding to pipe - -There is an unref when the message is sent. - -==17204== ERROR: AddressSanitizer: heap-use-after-free on address 0x6008000144a8 at pc 0x7fffee0ce245 bp 0x7fffffffc630 sp 0x7fffffffc620 -READ of size 4 at 0x6008000144a8 thread T0 - #0 0x7fffee0ce244 in smartcard_unref_vsc_msg_item /home/elmarco/src/spice/spice/server/smartcard.c:608 - #1 0x7fffee0cb451 in smartcard_unref_msg_to_client /home/elmarco/src/spice/spice/server/smartcard.c:178 - #2 0x7fffedfcdf14 in spice_char_device_read_from_device /home/elmarco/src/spice/spice/server/char-device.c:330 - #3 0x7fffedfd1763 in spice_char_device_wakeup /home/elmarco/src/spice/spice/server/char-device.c:901 - #4 0x7fffee05da98 in spice_server_char_device_wakeup /home/elmarco/src/spice/spice/server/reds.c:2990 - #5 0x55555593fa34 in spice_chr_write /home/elmarco/src/qemu/spice-qemu-char.c:189 - #6 0x5555559375f1 in qemu_chr_fe_write /home/elmarco/src/qemu/qemu-char.c:220 - #7 0x555555b3b682 in ccid_card_vscard_send_msg.isra.2 /home/elmarco/src/qemu/hw/usb/ccid-card-passthru.c:76 - #8 0x555555b3c466 in ccid_card_vscard_send_error /home/elmarco/src/qemu/hw/usb/ccid-card-passthru.c:91 - #9 0x555555b3c466 in ccid_card_vscard_handle_message /home/elmarco/src/qemu/hw/usb/ccid-card-passthru.c:242 - #10 0x555555b3c466 in ccid_card_vscard_read /home/elmarco/src/qemu/hw/usb/ccid-card-passthru.c:289 - #11 0x55555593f169 in vmc_write /home/elmarco/src/qemu/spice-qemu-char.c:41 - #12 0x7fffedfcee6d in spice_char_device_write_to_device /home/elmarco/src/spice/spice/server/char-device.c:477 - #13 0x7fffedfcfd31 in spice_char_device_write_buffer_add /home/elmarco/src/spice/spice/server/char-device.c:629 - #14 0x7fffee0ce9df in smartcard_channel_write_to_reader /home/elmarco/src/spice/spice/server/smartcard.c:675 - #15 0x7fffee0cc7db in smartcard_char_device_notify_reader_add /home/elmarco/src/spice/spice/server/smartcard.c:341 - #16 0x7fffee0ce4f3 in smartcard_add_reader /home/elmarco/src/spice/spice/server/smartcard.c:648 - #17 0x7fffee0cf2e2 in smartcard_channel_handle_message /home/elmarco/src/spice/spice/server/smartcard.c:763 - #18 0x7fffedffe21f in red_peer_handle_incoming /home/elmarco/src/spice/spice/server/red-channel.c:307 - #19 0x7fffedffe4f6 in red_channel_client_receive /home/elmarco/src/spice/spice/server/red-channel.c:325 - #20 0x7fffee00726c in red_channel_client_event /home/elmarco/src/spice/spice/server/red-channel.c:1566 - #21 0x555555c3c53d in qemu_iohandler_poll /home/elmarco/src/qemu/iohandler.c:143 - #22 0x555555c3b800 in main_loop_wait /home/elmarco/src/qemu/main-loop.c:504 - #23 0x5555556f160c in main_loop /home/elmarco/src/qemu/vl.c:1818 - #24 0x5555556f160c in main /home/elmarco/src/qemu/vl.c:4394 - #25 0x7fffed7d0b14 in __libc_start_main /usr/src/debug/glibc-2.17-c758a686/csu/libc-start.c:274 - #26 0x5555556f9c20 in _start (/home/elmarco/src/qemu/x86_64-softmmu/qemu-system-x86_64+0x1a5c20) -0x6008000144a8 is located 24 bytes inside of 40-byte region [0x600800014490,0x6008000144b8) -freed by thread T0 here: - #0 0x7ffff4e61009 in __interceptor_free /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libsanitizer/asan/../../../../libsanitizer/asan/asan_malloc_linux.cc:61 - #1 0x7fffee0ce2a1 in smartcard_unref_vsc_msg_item /home/elmarco/src/spice/spice/server/smartcard.c:610 - #2 0x7fffee0cdd58 in smartcard_channel_release_pipe_item /home/elmarco/src/spice/spice/server/smartcard.c:548 - #3 0x7fffee000668 in red_channel_client_release_item /home/elmarco/src/spice/spice/server/red-channel.c:602 - #4 0x7fffee0006ef in red_channel_client_release_sent_item /home/elmarco/src/spice/spice/server/red-channel.c:609 - #5 0x7fffee0007b5 in red_channel_peer_on_out_msg_done /home/elmarco/src/spice/spice/server/red-channel.c:620 - #6 0x7fffedffed7e in red_peer_handle_outgoing /home/elmarco/src/spice/spice/server/red-channel.c:385 - #7 0x7fffee0057bb in red_channel_client_send /home/elmarco/src/spice/spice/server/red-channel.c:1294 - #8 0x7fffee0076e6 in red_channel_client_begin_send_message /home/elmarco/src/spice/spice/server/red-channel.c:1605 - #9 0x7fffee0cdccd in smartcard_channel_send_item /home/elmarco/src/spice/spice/server/smartcard.c:541 - #10 0x7fffee000570 in red_channel_client_send_item /home/elmarco/src/spice/spice/server/red-channel.c:588 - #11 0x7fffee005bfb in red_channel_client_push /home/elmarco/src/spice/spice/server/red-channel.c:1347 - #12 0x7fffee007ef7 in red_channel_client_pipe_add_push /home/elmarco/src/spice/spice/server/red-channel.c:1673 - #13 0x7fffee0cde4d in smartcard_channel_client_pipe_add_push /home/elmarco/src/spice/spice/server/smartcard.c:571 - #14 0x7fffee0cb567 in smartcard_send_msg_to_client /home/elmarco/src/spice/spice/server/smartcard.c:187 - #15 0x7fffedfcdba2 in spice_char_device_send_msg_to_clients /home/elmarco/src/spice/spice/server/char-device.c:282 - #16 0x7fffedfcdea4 in spice_char_device_read_from_device /home/elmarco/src/spice/spice/server/char-device.c:329 - #17 0x7fffedfd1763 in spice_char_device_wakeup /home/elmarco/src/spice/spice/server/char-device.c:901 - #18 0x7fffee05da98 in spice_server_char_device_wakeup /home/elmarco/src/spice/spice/server/reds.c:2990 - #19 0x55555593fa34 in spice_chr_write /home/elmarco/src/qemu/spice-qemu-char.c:189 - -Signed-off-by: Marc-Andre Lureau ---- - server/smartcard.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/server/smartcard.c b/server/smartcard.c -index aad22aa..8d529fe 100644 ---- a/server/smartcard.c -+++ b/server/smartcard.c -@@ -172,14 +172,17 @@ static void smartcard_unref_msg_to_client(SpiceCharDeviceMsgToClient *msg, - smartcard_unref_vsc_msg_item((MsgItem *)msg); - } - --static void smartcard_send_msg_to_client(SpiceCharDeviceMsgToClient *msg, -+static void smartcard_send_msg_to_client(SpiceCharDeviceMsgToClient *message, - RedClient *client, - void *opaque) - { - SmartCardDeviceState *dev = opaque; -- spice_assert(dev->scc && dev->scc->base.client == client); -- smartcard_channel_client_pipe_add_push(&dev->scc->base, &((MsgItem *)msg)->base); -+ MsgItem *msg = (MsgItem *)message; -+ PipeItem *item = &msg->base; - -+ spice_assert(dev->scc && dev->scc->base.client == client); -+ smartcard_ref_vsc_msg_item(msg); -+ smartcard_channel_client_pipe_add_push(&dev->scc->base, item); - } - - static void smartcard_send_tokens_to_client(RedClient *client, uint32_t tokens, void *opaque) diff --git a/SOURCES/0066-smartcard-allocate-msg-with-the-expected-size.patch b/SOURCES/0066-smartcard-allocate-msg-with-the-expected-size.patch deleted file mode 100644 index 671fc43..0000000 --- a/SOURCES/0066-smartcard-allocate-msg-with-the-expected-size.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Marc-Andre Lureau -Date: Thu, 17 Dec 2015 18:16:22 +0100 -Subject: [PATCH] smartcard: allocate msg with the expected size - -==529== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60040009c098 at pc 0x7fffee0eda6d bp 0x7fffffffcd00 sp 0x7fffffffccf0 -WRITE of size 4 at 0x60040009c098 thread T0 - #0 0x7fffee0eda6c in smartcard_char_device_notify_reader_add /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:334 - #1 0x7fffee0ef783 in smartcard_add_reader /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:642 - #2 0x7fffee0f0568 in smartcard_channel_handle_message /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:757 - #3 0x7fffee032f3f in red_peer_handle_incoming /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:304 - #4 0x7fffee033216 in red_channel_client_receive /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:322 - #5 0x7fffee03bf1f in red_channel_client_event /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:1561 - #6 0x555555c3c53d in qemu_iohandler_poll /home/elmarco/src/qemu/iohandler.c:143 - #7 0x555555c3b800 in main_loop_wait /home/elmarco/src/qemu/main-loop.c:504 - #8 0x5555556f160c in main_loop /home/elmarco/src/qemu/vl.c:1818 - #9 0x5555556f160c in main /home/elmarco/src/qemu/vl.c:4394 - #10 0x7fffed80eb14 in __libc_start_main /usr/src/debug/glibc-2.17-c758a686/csu/libc-start.c:274 - #11 0x5555556f9c20 in _start (/home/elmarco/src/qemu/x86_64-softmmu/qemu-system-x86_64+0x1a5c20) -0x60040009c098 is located 0 bytes to the right of 8-byte region [0x60040009c090,0x60040009c098) -allocated by thread T0 here: - #0 0x7ffff4e612be in __interceptor_realloc /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libsanitizer/asan/../../../../libsanitizer/asan/asan_malloc_linux.cc:92 - #1 0x7fffee121308 in spice_realloc /home/elmarco/pkg/spice/spice-0.12.4/spice-common/common/mem.c:123 - #2 0x7fffee004a48 in __spice_char_device_write_buffer_get /home/elmarco/pkg/spice/spice-0.12.4/server/char_device.c:516 - #3 0x7fffee004e87 in spice_char_device_write_buffer_get /home/elmarco/pkg/spice/spice-0.12.4/server/char_device.c:557 - #4 0x7fffee0ed8b9 in smartcard_char_device_notify_reader_add /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:325 - #5 0x7fffee0ef783 in smartcard_add_reader /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:642 - #6 0x7fffee0f0568 in smartcard_channel_handle_message /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:757 - #7 0x7fffee032f3f in red_peer_handle_incoming /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:304 - #8 0x7fffee033216 in red_channel_client_receive /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:322 - #9 0x7fffee03bf1f in red_channel_client_event /home/elmarco/pkg/spice/spice-0.12.4/server/red_channel.c:1561 - #10 0x555555c3c53d in qemu_iohandler_poll /home/elmarco/src/qemu/iohandler.c:143 -SUMMARY: AddressSanitizer: heap-buffer-overflow /home/elmarco/pkg/spice/spice-0.12.4/server/smartcard.c:334 smartcard_char_device_notify_reader_add - -Signed-off-by: Marc-Andre Lureau ---- - server/smartcard.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/server/smartcard.c b/server/smartcard.c -index 8d529fe..3043ad1 100644 ---- a/server/smartcard.c -+++ b/server/smartcard.c -@@ -325,7 +325,7 @@ static void smartcard_char_device_notify_reader_add(SmartCardDeviceState *st) - SpiceCharDeviceWriteBuffer *write_buf; - VSCMsgHeader *vheader; - -- write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(vheader)); -+ write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(*vheader)); - if (!write_buf) { - spice_error("failed to allocate write buffer"); - return; -@@ -372,7 +372,7 @@ static void smartcard_char_device_notify_reader_remove(SmartCardDeviceState *st) - spice_debug("reader add was never sent to the device"); - return; - } -- write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(vheader)); -+ write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(*vheader)); - if (!write_buf) { - spice_error("failed to allocate write buffer"); - return; diff --git a/SOURCES/0067-create-a-function-to-validate-surface-parameters.patch b/SOURCES/0067-create-a-function-to-validate-surface-parameters.patch deleted file mode 100644 index a1f0c64..0000000 --- a/SOURCES/0067-create-a-function-to-validate-surface-parameters.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Mon, 29 Feb 2016 14:24:03 +0000 -Subject: [PATCH] create a function to validate surface parameters - -Make possible to reuse it outside red-parse-qxl.c - -Signed-off-by: Frediano Ziglio ---- - server/red_parse_qxl.c | 50 ++++++++++++++++++++++++++++++++------------------ - server/red_parse_qxl.h | 5 +++++ - 2 files changed, 37 insertions(+), 18 deletions(-) - -diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c -index bd0c408..7dc6a4d 100644 ---- a/server/red_parse_qxl.c -+++ b/server/red_parse_qxl.c -@@ -19,7 +19,6 @@ - #include - #endif - --#include - #include - #include - #include "common/lz_common.h" -@@ -1306,13 +1305,41 @@ static unsigned int surface_format_to_bpp(uint32_t format) - return 0; - } - -+bool red_validate_surface(uint32_t width, uint32_t height, -+ int32_t stride, uint32_t format) -+{ -+ unsigned int bpp; -+ uint64_t size; -+ -+ bpp = surface_format_to_bpp(format); -+ -+ /* check if format is valid */ -+ if (!bpp) { -+ return false; -+ } -+ -+ /* check stride is larger than required bytes */ -+ size = ((uint64_t) width * bpp + 7u) / 8u; -+ /* the uint32_t conversion is here to avoid problems with -2^31 value */ -+ if (stride == G_MININT32 || size > (uint32_t) abs(stride)) { -+ return false; -+ } -+ -+ /* the multiplication can overflow, also abs(-2^31) may return a negative value */ -+ size = (uint64_t) height * abs(stride); -+ if (size > MAX_DATA_CHUNK) { -+ return false; -+ } -+ -+ return true; -+} -+ - 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); -@@ -1331,26 +1358,13 @@ 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) { -+ if (!red_validate_surface(red->u.surface_create.width, red->u.surface_create.height, -+ red->u.surface_create.stride, red->u.surface_create.format)) { - 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) { -- return 1; -- } -+ size = red->u.surface_create.height * abs(red->u.surface_create.stride); - red->u.surface_create.data = - (uint8_t*)get_virt(slots, qxl->u.surface_create.data, size, group_id, &error); - if (error) { -diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h -index 3adc9fa..e18d8d0 100644 ---- a/server/red_parse_qxl.h -+++ b/server/red_parse_qxl.h -@@ -19,6 +19,8 @@ - #ifndef RED_ABI_TRANSLATE_H - #define RED_ABI_TRANSLATE_H - -+#include -+ - #include - #include "red_common.h" - #include "red_memslots.h" -@@ -128,6 +130,9 @@ int red_get_message(RedMemSlotInfo *slots, int group_id, - RedMessage *red, QXLPHYSICAL addr); - void red_put_message(RedMessage *red); - -+bool red_validate_surface(uint32_t width, uint32_t height, -+ int32_t stride, uint32_t format); -+ - int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id, - RedSurfaceCmd *red, QXLPHYSICAL addr); - void red_put_surface_cmd(RedSurfaceCmd *red); diff --git a/SOURCES/0068-improve-primary-surface-parameter-checks.patch b/SOURCES/0068-improve-primary-surface-parameter-checks.patch deleted file mode 100644 index 8005e06..0000000 --- a/SOURCES/0068-improve-primary-surface-parameter-checks.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Mon, 29 Feb 2016 14:34:49 +0000 -Subject: [PATCH] improve primary surface parameter checks - -Primary surface, as additional surfaces, can be used to access -host memory from the guest using invalid parameters. - -Signed-off-by: Frediano Ziglio ---- - server/red_worker.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/server/red_worker.c b/server/red_worker.c -index a7eaab9..f9179a6 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -11380,6 +11380,15 @@ static void dev_create_primary_surface(RedWorker *worker, uint32_t surface_id, - spice_warn_if(((uint64_t)abs(surface.stride) * (uint64_t)surface.height) != - abs(surface.stride) * surface.height); - -+ /* surface can arrive from guest unchecked so make sure -+ * guest is not a malicious one and drop invalid requests -+ */ -+ if (!red_validate_surface(surface.width, surface.height, -+ surface.stride, surface.format)) { -+ spice_warning("wrong primary surface creation request"); -+ return; -+ } -+ - line_0 = (uint8_t*)get_virt(&worker->mem_slots, surface.mem, - surface.height * abs(surface.stride), - surface.group_id, &error); diff --git a/SOURCES/0069-reds-Do-not-abort-due-to-wrong-header.patch b/SOURCES/0069-reds-Do-not-abort-due-to-wrong-header.patch deleted file mode 100644 index a420d2f..0000000 --- a/SOURCES/0069-reds-Do-not-abort-due-to-wrong-header.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Pavel Grunt -Date: Fri, 13 Nov 2015 09:14:29 +0100 -Subject: [PATCH] reds: Do not abort due to wrong header -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Just prevent the buggy client from connecting. - - #0 0x00007fffe83b2a98 in raise () at /lib64/libc.so.6 - #1 0x00007fffe83b469a in abort () at /lib64/libc.so.6 - #2 0x00007ffff7b1533d in spice_logv (log_domain=0x7ffff7b87226 "Spice", log_level=SPICE_LOG_LEVEL_ERROR, strloc=0x7ffff7b92aba "reds.c:1373", function=0x7ffff7b94f40 <__FUNCTION__.31775> "reds_send_link_ack", format=0x7ffff7b871fe "assertion `%s' failed", args=args@entry=0x7fffffffcb68) at log.c:109 - #3 0x00007ffff7b15468 in spice_log (log_domain=log_domain@entry=0x7ffff7b87226 "Spice", log_level=log_level@entry=SPICE_LOG_LEVEL_ERROR, strloc=strloc@entry=0x7ffff7b92aba "reds.c:1373", function=function@entry=0x7ffff7b94f40 <__FUNCTION__.31775> "reds_send_link_ack", format=format@entry=0x7ffff7b871fe "assertion `%s' failed") at log.c:123 - #4 0x00007ffff7aee335 in reds_handle_read_link_done (link=0x555556b27c70) - at reds.c:1373 - #5 0x00007ffff7aee335 in reds_handle_read_link_done (opaque=0x555556b27c70) - at reds.c:2139 - #6 0x000055555588acc6 in qemu_iohandler_poll () - #7 0x000055555588a8e1 in main_loop_wait () - #8 0x0000555555614064 in main () - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1281442 - -Acked-by: Fabiano Fidêncio -Acked-by: Frediano Ziglio ---- - server/reds.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/server/reds.c b/server/reds.c -index e96f28d..b45c44f 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1482,7 +1482,10 @@ static int reds_send_link_ack(RedLinkInfo *link) - channel = reds_find_channel(link->link_mess->channel_type, - link->link_mess->channel_id); - if (!channel) { -- spice_assert(link->link_mess->channel_type == SPICE_CHANNEL_MAIN); -+ if (link->link_mess->channel_type != SPICE_CHANNEL_MAIN) { -+ spice_warning("Received wrong header: channel_type != SPICE_CHANNEL_MAIN"); -+ return FALSE; -+ } - spice_assert(reds->main_channel); - channel = &reds->main_channel->base; - } diff --git a/SOURCES/0070-memslot-do-not-crash-if-guest-provide-a-wrong-addres.patch b/SOURCES/0070-memslot-do-not-crash-if-guest-provide-a-wrong-addres.patch deleted file mode 100644 index 29787ce..0000000 --- a/SOURCES/0070-memslot-do-not-crash-if-guest-provide-a-wrong-addres.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Wed, 17 Feb 2016 21:22:22 +0000 -Subject: [PATCH] memslot: do not crash if guest provide a wrong address - -This could happen with buggy driver. - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1264356 - -Signed-off-by: Frediano Ziglio -Acked-by: Pavel Grunt ---- - server/red_memslots.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/server/red_memslots.c b/server/red_memslots.c -index d9153d3..3b8443e 100644 ---- a/server/red_memslots.c -+++ b/server/red_memslots.c -@@ -87,7 +87,7 @@ int validate_virt(RedMemSlotInfo *info, unsigned long virt, int slot_id, - - if (virt < slot->virt_start_addr || (virt + add_size) > slot->virt_end_addr) { - print_memslots(info); -- spice_critical("virtual address out of range\n" -+ spice_warning("virtual address out of range\n" - " virt=0x%lx+0x%x slot_id=%d group_id=%d\n" - " slot=0x%lx-0x%lx delta=0x%lx", - virt, add_size, slot_id, group_id, diff --git a/SOURCES/0071-red-channel-make-red_client_-ref-unref-thread-safe.patch b/SOURCES/0071-red-channel-make-red_client_-ref-unref-thread-safe.patch deleted file mode 100644 index a429d17..0000000 --- a/SOURCES/0071-red-channel-make-red_client_-ref-unref-thread-safe.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 12 Apr 2016 16:28:07 +0100 -Subject: [PATCH] red-channel: make red_client_{ref,unref} thread safe - -These function are called on both sides of dispatcher so the -increment/decrement of the counter is done in multiple threads. -This caused the counter to not get incremented correctly and -freed the structure too early, leaving a dangling pointer in -the other thread. - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1253375. - -Signed-off-by: Frediano Ziglio -Acked-by: Christophe Fergeau -Acked-by: Jonathon Jongsma ---- - server/red_channel.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/server/red_channel.c b/server/red_channel.c -index 449e628..82e7137 100644 ---- a/server/red_channel.c -+++ b/server/red_channel.c -@@ -2060,13 +2060,13 @@ RedClient *red_client_new(int migrated) - RedClient *red_client_ref(RedClient *client) - { - spice_assert(client); -- client->refs++; -+ g_atomic_int_inc(&client->refs); - return client; - } - - RedClient *red_client_unref(RedClient *client) - { -- if (!--client->refs) { -+ if (g_atomic_int_dec_and_test(&client->refs)) { - spice_debug("release client=%p", client); - pthread_mutex_destroy(&client->lock); - free(client); diff --git a/SOURCES/0072-chardev-remove-write-polling.patch b/SOURCES/0072-chardev-remove-write-polling.patch deleted file mode 100644 index 4ad544b..0000000 --- a/SOURCES/0072-chardev-remove-write-polling.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 24 Oct 2014 10:51:05 +0200 -Subject: [PATCH] chardev: remove write polling - -In an effort to reduce the wakeups per second, get rid of the -"write_to_dev" timer when the implementation supports -SPICE_CHAR_DEVICE_NOTIFY_WRITABLE. - -When this flag is set, the frontend instance is responsible for calling -spice_char_device_wakeup() when the device is ready to perform IO. - -Related to: -https://bugzilla.redhat.com/show_bug.cgi?id=912763 ---- - server/char_device.c | 36 +++++++++++++++++++++++++++--------- - server/spice.h | 7 ++++++- - 2 files changed, 33 insertions(+), 10 deletions(-) - -diff --git a/server/char_device.c b/server/char_device.c -index 6d2339e..c6dc45b 100644 ---- a/server/char_device.c -+++ b/server/char_device.c -@@ -438,7 +438,10 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - } - - spice_char_device_state_ref(dev); -- core->timer_cancel(dev->write_to_dev_timer); -+ -+ if (dev->write_to_dev_timer) { -+ core->timer_cancel(dev->write_to_dev_timer); -+ } - - sif = SPICE_CONTAINEROF(dev->sin->base.sif, SpiceCharDeviceInterface, base); - while (dev->running) { -@@ -473,8 +476,10 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - /* retry writing as long as the write queue is not empty */ - if (dev->running) { - if (dev->cur_write_buf) { -- core->timer_start(dev->write_to_dev_timer, -- CHAR_DEVICE_WRITE_TO_TIMEOUT); -+ if (dev->write_to_dev_timer) { -+ core->timer_start(dev->write_to_dev_timer, -+ CHAR_DEVICE_WRITE_TO_TIMEOUT); -+ } - } else { - spice_assert(ring_is_empty(&dev->write_queue)); - } -@@ -488,7 +493,9 @@ static void spice_char_dev_write_retry(void *opaque) - { - SpiceCharDeviceState *dev = opaque; - -- core->timer_cancel(dev->write_to_dev_timer); -+ if (dev->write_to_dev_timer) { -+ core->timer_cancel(dev->write_to_dev_timer); -+ } - spice_char_device_write_to_device(dev); - } - -@@ -635,6 +642,7 @@ SpiceCharDeviceState *spice_char_device_state_create(SpiceCharDeviceInstance *si - void *opaque) - { - SpiceCharDeviceState *char_dev; -+ SpiceCharDeviceInterface *sif; - - spice_assert(sin); - spice_assert(cbs->read_one_msg_from_device && cbs->ref_msg_to_client && -@@ -652,10 +660,15 @@ SpiceCharDeviceState *spice_char_device_state_create(SpiceCharDeviceInstance *si - ring_init(&char_dev->write_bufs_pool); - ring_init(&char_dev->clients); - -- char_dev->write_to_dev_timer = core->timer_add(spice_char_dev_write_retry, char_dev); -- if (!char_dev->write_to_dev_timer) { -- spice_error("failed creating char dev write timer"); -+ sif = SPICE_CONTAINEROF(char_dev->sin->base.sif, SpiceCharDeviceInterface, base); -+ if (sif->base.minor_version <= 2 || -+ !(sif->flags & SPICE_CHAR_DEVICE_NOTIFY_WRITABLE)) { -+ char_dev->write_to_dev_timer = core->timer_add(spice_char_dev_write_retry, char_dev); -+ if (!char_dev->write_to_dev_timer) { -+ spice_error("failed creating char dev write timer"); -+ } - } -+ - char_dev->refs = 1; - sin->st = char_dev; - spice_debug("sin %p dev_state %p", sin, char_dev); -@@ -697,7 +710,9 @@ static void spice_char_device_state_unref(SpiceCharDeviceState *char_dev) - void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev) - { - reds_on_char_device_state_destroy(char_dev); -- core->timer_remove(char_dev->write_to_dev_timer); -+ if (char_dev->write_to_dev_timer) { -+ core->timer_remove(char_dev->write_to_dev_timer); -+ } - write_buffers_queue_free(&char_dev->write_queue); - write_buffers_queue_free(&char_dev->write_bufs_pool); - if (char_dev->cur_write_buf) { -@@ -805,7 +820,9 @@ void spice_char_device_stop(SpiceCharDeviceState *dev) - spice_debug("dev_state %p", dev); - dev->running = FALSE; - dev->active = FALSE; -- core->timer_cancel(dev->write_to_dev_timer); -+ if (dev->write_to_dev_timer) { -+ core->timer_cancel(dev->write_to_dev_timer); -+ } - } - - void spice_char_device_reset(SpiceCharDeviceState *dev) -@@ -842,6 +859,7 @@ void spice_char_device_reset(SpiceCharDeviceState *dev) - - void spice_char_device_wakeup(SpiceCharDeviceState *dev) - { -+ spice_char_device_write_to_device(dev); - spice_char_device_read_from_device(dev); - } - -diff --git a/server/spice.h b/server/spice.h -index 6fbb7b2..7b5e04e 100644 ---- a/server/spice.h -+++ b/server/spice.h -@@ -390,11 +390,15 @@ void spice_server_record_set_mute(SpiceRecordInstance *sin, uint8_t mute); - - #define SPICE_INTERFACE_CHAR_DEVICE "char_device" - #define SPICE_INTERFACE_CHAR_DEVICE_MAJOR 1 --#define SPICE_INTERFACE_CHAR_DEVICE_MINOR 2 -+#define SPICE_INTERFACE_CHAR_DEVICE_MINOR 3 - typedef struct SpiceCharDeviceInterface SpiceCharDeviceInterface; - typedef struct SpiceCharDeviceInstance SpiceCharDeviceInstance; - typedef struct SpiceCharDeviceState SpiceCharDeviceState; - -+typedef enum { -+ SPICE_CHAR_DEVICE_NOTIFY_WRITABLE = 1 << 0, -+} spice_char_device_flags; -+ - struct SpiceCharDeviceInterface { - SpiceBaseInterface base; - -@@ -402,6 +406,7 @@ struct SpiceCharDeviceInterface { - int (*write)(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len); - int (*read)(SpiceCharDeviceInstance *sin, uint8_t *buf, int len); - void (*event)(SpiceCharDeviceInstance *sin, uint8_t event); -+ spice_char_device_flags flags; - }; - - struct SpiceCharDeviceInstance { diff --git a/SOURCES/0073-clean-up-remove-unused-function.patch b/SOURCES/0073-clean-up-remove-unused-function.patch deleted file mode 100644 index 8b7b2fb..0000000 --- a/SOURCES/0073-clean-up-remove-unused-function.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Mon, 18 Nov 2013 11:28:27 +0100 -Subject: [PATCH] clean-up: remove unused function - ---- - server/reds.c | 5 ----- - server/reds.h | 1 - - 2 files changed, 6 deletions(-) - -diff --git a/server/reds.c b/server/reds.c -index b45c44f..53f21bd 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -3572,11 +3572,6 @@ uint32_t reds_get_mm_time(void) - return time_space.tv_sec * 1000 + time_space.tv_nsec / 1000 / 1000; - } - --void reds_update_mm_timer(uint32_t mm_time) --{ -- red_dispatcher_set_mm_time(mm_time); --} -- - void reds_enable_mm_timer(void) - { - core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS); -diff --git a/server/reds.h b/server/reds.h -index 1c5ae84..24b4d95 100644 ---- a/server/reds.h -+++ b/server/reds.h -@@ -122,7 +122,6 @@ void reds_handle_channel_event(int event, SpiceChannelEventInfo *info); - - void reds_disable_mm_timer(void); - void reds_enable_mm_timer(void); --void reds_update_mm_timer(uint32_t mm_time); - uint32_t reds_get_mm_time(void); - void reds_set_client_mouse_allowed(int is_client_mouse_allowed, - int x_res, int y_res); diff --git a/SOURCES/0074-Remove-guest-side-video-time-stamping.patch b/SOURCES/0074-Remove-guest-side-video-time-stamping.patch deleted file mode 100644 index 28f0440..0000000 --- a/SOURCES/0074-Remove-guest-side-video-time-stamping.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Sun, 2 Nov 2014 22:11:58 +0100 -Subject: [PATCH] Remove guest side video time-stamping - -The multimedia time is defined by the server side monotonic time [1], -but the drawing time-stamp is done in guest side, so it requires -synchronization between host and guest. This is expensive, when no audio -is playing, there is a ~30x/sec wakeup to update the qxl device mmtime, -and it requires marking dirty the rom region. - -Instead, the video timestamping can be done more efficiently on server -side, without visible drawbacks. - -[1] a better timestamp could be the audio time, since audio players are - usually sync with audio time) - -Related to: -https://bugzilla.redhat.com/show_bug.cgi?id=912763 ---- - server/red_dispatcher.c | 9 --------- - server/red_worker.c | 1 + - server/reds-private.h | 2 -- - server/reds.c | 13 ------------- - server/snd_worker.c | 1 - - server/spice.h | 3 ++- - 6 files changed, 3 insertions(+), 26 deletions(-) - -diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c -index 2ebde63..6ecd3d4 100644 ---- a/server/red_dispatcher.c -+++ b/server/red_dispatcher.c -@@ -749,15 +749,6 @@ static void qxl_worker_loadvm_commands(QXLWorker *qxl_worker, - red_dispatcher_loadvm_commands((RedDispatcher*)qxl_worker, ext, count); - } - --void red_dispatcher_set_mm_time(uint32_t mm_time) --{ -- RedDispatcher *now = dispatchers; -- while (now) { -- now->qxl->st->qif->set_mm_time(now->qxl, mm_time); -- now = now->next; -- } --} -- - static inline int calc_compression_level(void) - { - spice_assert(streaming_video != STREAM_VIDEO_INVALID); -diff --git a/server/red_worker.c b/server/red_worker.c -index f9179a6..dfa5274 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -4237,6 +4237,7 @@ static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable - return; - } - -+ drawable->mm_time = reds_get_mm_time(); - surface_id = item->surface_id; - - worker->surfaces[surface_id].refs++; -diff --git a/server/reds-private.h b/server/reds-private.h -index 9358d27..46899f6 100644 ---- a/server/reds-private.h -+++ b/server/reds-private.h -@@ -6,7 +6,6 @@ - #include - - #define MIGRATE_TIMEOUT (1000 * 10) /* 10sec */ --#define MM_TIMER_GRANULARITY_MS (1000 / 30) - #define MM_TIME_DELTA 400 /*ms*/ - - typedef struct TicketAuthentication { -@@ -159,7 +158,6 @@ typedef struct RedsState { - int dispatcher_allows_client_mouse; - MonitorMode monitor_mode; - SpiceTimer *mig_timer; -- SpiceTimer *mm_timer; - - int vm_running; - Ring char_devs_states; /* list of SpiceCharDeviceStateItem */ -diff --git a/server/reds.c b/server/reds.c -index 53f21bd..f4c6d1d 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -3574,7 +3574,6 @@ uint32_t reds_get_mm_time(void) - - void reds_enable_mm_timer(void) - { -- core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS); - reds->mm_timer_enabled = TRUE; - reds->mm_time_latency = MM_TIME_DELTA; - reds_send_mm_time(); -@@ -3582,16 +3581,9 @@ void reds_enable_mm_timer(void) - - void reds_disable_mm_timer(void) - { -- core->timer_cancel(reds->mm_timer); - reds->mm_timer_enabled = FALSE; - } - --static void mm_timer_proc(void *opaque) --{ -- red_dispatcher_set_mm_time(reds_get_mm_time()); -- core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS); --} -- - static SpiceCharDeviceState *attach_to_red_agent(SpiceCharDeviceInstance *sin) - { - VDIPortState *state = &reds->agent_state; -@@ -4029,11 +4021,6 @@ static int do_spice_init(SpiceCoreInterface *core_interface) - } - #endif - -- if (!(reds->mm_timer = core->timer_add(mm_timer_proc, NULL))) { -- spice_error("mm timer create failed"); -- } -- reds_enable_mm_timer(); -- - if (reds_init_net() < 0) { - goto err; - } -diff --git a/server/snd_worker.c b/server/snd_worker.c -index c451031..b6cb62b 100644 ---- a/server/snd_worker.c -+++ b/server/snd_worker.c -@@ -1113,7 +1113,6 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance - snd_playback_free_frame(playback_channel, playback_channel->pending_frame); - } - frame->time = reds_get_mm_time(); -- red_dispatcher_set_mm_time(frame->time); - playback_channel->pending_frame = frame; - snd_set_command(&playback_channel->base, SND_PLAYBACK_PCM_MASK); - snd_playback_send(&playback_channel->base); -diff --git a/server/spice.h b/server/spice.h -index 7b5e04e..9c8e18a 100644 ---- a/server/spice.h -+++ b/server/spice.h -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - #include - -@@ -228,7 +229,7 @@ struct QXLInterface { - - void (*attache_worker)(QXLInstance *qin, QXLWorker *qxl_worker); - void (*set_compression_level)(QXLInstance *qin, int level); -- void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time); -+ void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time) SPICE_GNUC_DEPRECATED; - - void (*get_init_info)(QXLInstance *qin, QXLDevInitInfo *info); - int (*get_command)(QXLInstance *qin, struct QXLCommandExt *cmd); diff --git a/SOURCES/0075-char-device-fix-usage-of-free-unref-on-WriteBuffer.patch b/SOURCES/0075-char-device-fix-usage-of-free-unref-on-WriteBuffer.patch deleted file mode 100644 index 80704a0..0000000 --- a/SOURCES/0075-char-device-fix-usage-of-free-unref-on-WriteBuffer.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Toso -Date: Wed, 19 Aug 2015 10:53:22 +0200 -Subject: [PATCH] char-device: fix usage of free/unref on WriteBuffer - -There are places were the could should definetly free the -SpiceCharDeviceWriteBuffer and places that it should only unref it. The -current use of spice_char_device_write_buffer_free was missleading. - -This patch creates the spice_char_device_write_buffer_unref and properly -call these two functions. - -Related: https://bugs.freedesktop.org/show_bug.cgi?id=91350 ---- - server/char_device.c | 34 ++++++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 12 deletions(-) - -diff --git a/server/char_device.c b/server/char_device.c -index c6dc45b..dd367ab 100644 ---- a/server/char_device.c -+++ b/server/char_device.c -@@ -80,6 +80,7 @@ enum { - * destroyed during a callback */ - static void spice_char_device_state_ref(SpiceCharDeviceState *char_dev); - static void spice_char_device_state_unref(SpiceCharDeviceState *char_dev); -+static void spice_char_device_write_buffer_unref(SpiceCharDeviceWriteBuffer *write_buf); - - static void spice_char_dev_write_retry(void *opaque); - -@@ -90,10 +91,11 @@ typedef struct SpiceCharDeviceMsgToClientItem { - - static void spice_char_device_write_buffer_free(SpiceCharDeviceWriteBuffer *buf) - { -- if (--buf->refs == 0) { -- free(buf->buf); -- free(buf); -- } -+ if (buf == NULL) -+ return; -+ -+ free(buf->buf); -+ free(buf); - } - - static void write_buffers_queue_free(Ring *write_queue) -@@ -116,9 +118,11 @@ static void spice_char_device_write_buffer_pool_add(SpiceCharDeviceState *dev, - buf->origin = WRITE_BUFFER_ORIGIN_NONE; - buf->client = NULL; - ring_add(&dev->write_bufs_pool, &buf->link); -- } else { -- --buf->refs; -+ return; - } -+ -+ /* Buffer still being used - just unref for the caller */ -+ spice_char_device_write_buffer_unref(buf); - } - - static void spice_char_device_client_send_queue_free(SpiceCharDeviceState *dev, -@@ -581,6 +585,15 @@ static SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_ref(SpiceCharD - return write_buf; - } - -+static void spice_char_device_write_buffer_unref(SpiceCharDeviceWriteBuffer *write_buf) -+{ -+ spice_assert(write_buf); -+ -+ write_buf->refs--; -+ if (write_buf->refs == 0) -+ spice_char_device_write_buffer_free(write_buf); -+} -+ - void spice_char_device_write_buffer_add(SpiceCharDeviceState *dev, - SpiceCharDeviceWriteBuffer *write_buf) - { -@@ -607,8 +620,7 @@ void spice_char_device_write_buffer_release(SpiceCharDeviceState *dev, - spice_assert(!ring_item_is_linked(&write_buf->link)); - if (!dev) { - spice_printerr("no device. write buffer is freed"); -- free(write_buf->buf); -- free(write_buf); -+ spice_char_device_write_buffer_free(write_buf); - return; - } - -@@ -715,9 +727,7 @@ void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev) - } - write_buffers_queue_free(&char_dev->write_queue); - write_buffers_queue_free(&char_dev->write_bufs_pool); -- if (char_dev->cur_write_buf) { -- spice_char_device_write_buffer_free(char_dev->cur_write_buf); -- } -+ spice_char_device_write_buffer_free(char_dev->cur_write_buf); - - while (!ring_is_empty(&char_dev->clients)) { - RingItem *item = ring_get_tail(&char_dev->clients); -@@ -883,7 +893,7 @@ static void migrate_data_marshaller_write_buffer_free(uint8_t *data, void *opaqu - { - SpiceCharDeviceWriteBuffer *write_buf = (SpiceCharDeviceWriteBuffer *)opaque; - -- spice_char_device_write_buffer_free(write_buf); -+ spice_char_device_write_buffer_unref(write_buf); - } - - void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev, diff --git a/SOURCES/0076-spicevmc-set-state-of-DeviceInstance-to-NULL.patch b/SOURCES/0076-spicevmc-set-state-of-DeviceInstance-to-NULL.patch deleted file mode 100644 index f5afa21..0000000 --- a/SOURCES/0076-spicevmc-set-state-of-DeviceInstance-to-NULL.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Toso -Date: Fri, 13 Nov 2015 10:46:43 +0100 -Subject: [PATCH] spicevmc: set state of DeviceInstance to NULL - -After spice_char_device_state_destroy is called spicevmc should not keep -reference to that memory. state->chardev_st and sin->st point to the -same SpiceCharDeviceState and both should be set to NULL when it is -destroyed. ---- - server/spicevmc.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/server/spicevmc.c b/server/spicevmc.c -index e10f183..94cb8a7 100644 ---- a/server/spicevmc.c -+++ b/server/spicevmc.c -@@ -559,6 +559,7 @@ void spicevmc_device_disconnect(SpiceCharDeviceInstance *sin) - } - spice_char_device_state_destroy(sin->st); - state->chardev_st = NULL; -+ sin->st = NULL; - - reds_unregister_channel(&state->channel); - free(state->pipe_item); diff --git a/SOURCES/0077-char-device-set-to-NULL-freed-pointers-on-destroy.patch b/SOURCES/0077-char-device-set-to-NULL-freed-pointers-on-destroy.patch deleted file mode 100644 index ef4660b..0000000 --- a/SOURCES/0077-char-device-set-to-NULL-freed-pointers-on-destroy.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Toso -Date: Fri, 13 Nov 2015 10:44:55 +0100 -Subject: [PATCH] char-device: set to NULL freed pointers on destroy - -As SpiceCharDeviceState is only unref'ed on -spice_char_device_state_destroy the same device could be destroyed more -then once so the pointers that are freed should be set to NULL. - -Related: https://bugzilla.redhat.com/show_bug.cgi?id=1281455 ---- - server/char_device.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/server/char_device.c b/server/char_device.c -index dd367ab..285299c 100644 ---- a/server/char_device.c -+++ b/server/char_device.c -@@ -724,10 +724,12 @@ void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev) - reds_on_char_device_state_destroy(char_dev); - if (char_dev->write_to_dev_timer) { - core->timer_remove(char_dev->write_to_dev_timer); -+ char_dev->write_to_dev_timer = NULL; - } - write_buffers_queue_free(&char_dev->write_queue); - write_buffers_queue_free(&char_dev->write_bufs_pool); - spice_char_device_write_buffer_free(char_dev->cur_write_buf); -+ char_dev->cur_write_buf = NULL; - - while (!ring_is_empty(&char_dev->clients)) { - RingItem *item = ring_get_tail(&char_dev->clients); diff --git a/SOURCES/0078-channel-add-option-tcp-keepalive-timeout-to-channels.patch b/SOURCES/0078-channel-add-option-tcp-keepalive-timeout-to-channels.patch deleted file mode 100644 index 8b81a8d..0000000 --- a/SOURCES/0078-channel-add-option-tcp-keepalive-timeout-to-channels.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sunny Shin -Date: Tue, 1 Dec 2015 13:46:30 +0900 -Subject: [PATCH] channel: add option tcp keepalive timeout to channels - ---- - server/reds-private.h | 1 + - server/reds.c | 22 ++++++++++++++++++++++ - server/spice-server.syms | 5 +++++ - server/spice.h | 1 + - 4 files changed, 29 insertions(+) - -diff --git a/server/reds-private.h b/server/reds-private.h -index 46899f6..0f7ab65 100644 ---- a/server/reds-private.h -+++ b/server/reds-private.h -@@ -162,6 +162,7 @@ typedef struct RedsState { - int vm_running; - Ring char_devs_states; /* list of SpiceCharDeviceStateItem */ - int seamless_migration_enabled; /* command line arg */ -+ int keepalive_timeout; - - SSL_CTX *ctx; - -diff --git a/server/reds.c b/server/reds.c -index f4c6d1d..a28027e 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -2899,6 +2899,21 @@ static RedLinkInfo *reds_init_client_connection(int socket) - } - } - -+ if (reds->keepalive_timeout > 0) { -+ int keepalive = 1; -+ if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) == -1) { -+ if (errno != ENOTSUP) { -+ spice_printerr("setsockopt for keepalive failed, %s", strerror(errno)); -+ } -+ } -+ if (setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, -+ &reds->keepalive_timeout, sizeof(reds->keepalive_timeout)) == -1) { -+ if (errno != ENOTSUP) { -+ spice_printerr("setsockopt for keepalive timeout failed, %s", strerror(errno)); -+ } -+ } -+ } -+ - link = spice_new0(RedLinkInfo, 1); - stream = spice_new0(RedsStream, 1); - stream->info = spice_new0(SpiceChannelEventInfo, 1); -@@ -4690,3 +4705,10 @@ void reds_stream_free(RedsStream *s) - - free(s); - } -+ -+SPICE_GNUC_VISIBLE void spice_server_set_keepalive_timeout(SpiceServer *s, int timeout) -+{ -+ spice_assert(s == reds); -+ reds->keepalive_timeout = timeout; -+ spice_debug("keepalive timeout=%d", timeout); -+} -diff --git a/server/spice-server.syms b/server/spice-server.syms -index 4f2dc37..9af3354 100644 ---- a/server/spice-server.syms -+++ b/server/spice-server.syms -@@ -145,3 +145,8 @@ SPICE_SERVER_0.12.4 { - global: - spice_server_set_agent_file_xfer; - } SPICE_SERVER_0.12.3; -+ -+SPICE_SERVER_0.12.7 { -+global: -+ spice_server_set_keepalive_timeout; -+} SPICE_SERVER_0.12.4; -diff --git a/server/spice.h b/server/spice.h -index 9c8e18a..c31839d 100644 ---- a/server/spice.h -+++ b/server/spice.h -@@ -508,6 +508,7 @@ int spice_server_set_playback_compression(SpiceServer *s, int enable); - int spice_server_set_agent_mouse(SpiceServer *s, int enable); - int spice_server_set_agent_copypaste(SpiceServer *s, int enable); - int spice_server_set_agent_file_xfer(SpiceServer *s, int enable); -+void spice_server_set_keepalive_timeout(SpiceServer *s, int timeout); - - int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen); - int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen); diff --git a/SOURCES/0079-Always-enable-TCP-keepalive.patch b/SOURCES/0079-Always-enable-TCP-keepalive.patch deleted file mode 100644 index be6db5c..0000000 --- a/SOURCES/0079-Always-enable-TCP-keepalive.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 2 Mar 2016 12:24:11 +0100 -Subject: [PATCH] Always enable TCP keepalive - -Always enabled, hardcoded interval -as per https://bugzilla.redhat.com/show_bug.cgi?id=1298590 ---- - server/reds.c | 40 ++++++++++++++++++++++++++-------------- - 1 file changed, 26 insertions(+), 14 deletions(-) - -diff --git a/server/reds.c b/server/reds.c -index a28027e..a848828 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -2876,6 +2876,31 @@ static void reds_handle_ssl_accept(int fd, int event, void *data) - reds_handle_new_link(link); - } - -+#define KEEPALIVE_TIMEOUT (10*60) -+ -+static bool reds_init_keepalive(int socket) -+{ -+ int keepalive = 1; -+ int keepalive_timeout = KEEPALIVE_TIMEOUT; -+ -+ if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) == -1) { -+ if (errno != ENOTSUP) { -+ spice_printerr("setsockopt for keepalive failed, %s", strerror(errno)); -+ return false; -+ } -+ } -+ -+ if (setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, -+ &keepalive_timeout, sizeof(keepalive_timeout)) == -1) { -+ if (errno != ENOTSUP) { -+ spice_printerr("setsockopt for keepalive timeout failed, %s", strerror(errno)); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ - static RedLinkInfo *reds_init_client_connection(int socket) - { - RedLinkInfo *link; -@@ -2899,20 +2924,7 @@ static RedLinkInfo *reds_init_client_connection(int socket) - } - } - -- if (reds->keepalive_timeout > 0) { -- int keepalive = 1; -- if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) == -1) { -- if (errno != ENOTSUP) { -- spice_printerr("setsockopt for keepalive failed, %s", strerror(errno)); -- } -- } -- if (setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, -- &reds->keepalive_timeout, sizeof(reds->keepalive_timeout)) == -1) { -- if (errno != ENOTSUP) { -- spice_printerr("setsockopt for keepalive timeout failed, %s", strerror(errno)); -- } -- } -- } -+ reds_init_keepalive(socket); - - link = spice_new0(RedLinkInfo, 1); - stream = spice_new0(RedsStream, 1); diff --git a/SOURCES/0080-Remove-spice_server_set_keepalive_timeout.patch b/SOURCES/0080-Remove-spice_server_set_keepalive_timeout.patch deleted file mode 100644 index 31f1f5b..0000000 --- a/SOURCES/0080-Remove-spice_server_set_keepalive_timeout.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 2 Mar 2016 12:25:23 +0100 -Subject: [PATCH] Remove spice_server_set_keepalive_timeout - -This public API is no longer needed as the keepalive interval does not -need to be configurable. This API was never in a stable 0.12 release, so -it's OK to remove it now. ---- - server/reds-private.h | 1 - - server/reds.c | 7 ------- - server/spice-server.syms | 5 ----- - server/spice.h | 1 - - 4 files changed, 14 deletions(-) - -diff --git a/server/reds-private.h b/server/reds-private.h -index 0f7ab65..46899f6 100644 ---- a/server/reds-private.h -+++ b/server/reds-private.h -@@ -162,7 +162,6 @@ typedef struct RedsState { - int vm_running; - Ring char_devs_states; /* list of SpiceCharDeviceStateItem */ - int seamless_migration_enabled; /* command line arg */ -- int keepalive_timeout; - - SSL_CTX *ctx; - -diff --git a/server/reds.c b/server/reds.c -index a848828..e7e4090 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -4717,10 +4717,3 @@ void reds_stream_free(RedsStream *s) - - free(s); - } -- --SPICE_GNUC_VISIBLE void spice_server_set_keepalive_timeout(SpiceServer *s, int timeout) --{ -- spice_assert(s == reds); -- reds->keepalive_timeout = timeout; -- spice_debug("keepalive timeout=%d", timeout); --} -diff --git a/server/spice-server.syms b/server/spice-server.syms -index 9af3354..4f2dc37 100644 ---- a/server/spice-server.syms -+++ b/server/spice-server.syms -@@ -145,8 +145,3 @@ SPICE_SERVER_0.12.4 { - global: - spice_server_set_agent_file_xfer; - } SPICE_SERVER_0.12.3; -- --SPICE_SERVER_0.12.7 { --global: -- spice_server_set_keepalive_timeout; --} SPICE_SERVER_0.12.4; -diff --git a/server/spice.h b/server/spice.h -index c31839d..9c8e18a 100644 ---- a/server/spice.h -+++ b/server/spice.h -@@ -508,7 +508,6 @@ int spice_server_set_playback_compression(SpiceServer *s, int enable); - int spice_server_set_agent_mouse(SpiceServer *s, int enable); - int spice_server_set_agent_copypaste(SpiceServer *s, int enable); - int spice_server_set_agent_file_xfer(SpiceServer *s, int enable); --void spice_server_set_keepalive_timeout(SpiceServer *s, int timeout); - - int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen); - int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen); diff --git a/SOURCES/0081-sound-do-not-modify-client-state-on-migration.patch b/SOURCES/0081-sound-do-not-modify-client-state-on-migration.patch deleted file mode 100644 index 1893ec9..0000000 --- a/SOURCES/0081-sound-do-not-modify-client-state-on-migration.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 24 Apr 2015 14:05:00 +0200 -Subject: [PATCH] sound: do not modify client state on migration - -During migration, a volume jump is observed by the client. This is due -to qemu setting up destination server with default sound state, and the -server sending it after the client is connected. The volume is later -restored after migration is finished so there is no need to send this -default state values on connection. - -Tested with both AC97 & HDA devices. - -Fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=1012868 ---- - server/snd_worker.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/server/snd_worker.c b/server/snd_worker.c -index b6cb62b..d1bfcae 100644 ---- a/server/snd_worker.c -+++ b/server/snd_worker.c -@@ -1223,7 +1223,10 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt - SPICE_PLAYBACK_CAP_CELT_0_5_1) ? - playback_compression : SPICE_AUDIO_DATA_MODE_RAW; - -- on_new_playback_channel(worker); -+ if (!red_client_during_migrate_at_target(client)) { -+ on_new_playback_channel(worker); -+ } -+ - if (worker->active) { - spice_server_playback_start(st->sin); - } diff --git a/SOURCES/0082-char-device-spice_char_device_write_to_device-protec.patch b/SOURCES/0082-char-device-spice_char_device_write_to_device-protec.patch deleted file mode 100644 index 44b250b..0000000 --- a/SOURCES/0082-char-device-spice_char_device_write_to_device-protec.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Uri Lublin -Date: Mon, 2 Feb 2015 12:35:59 +0200 -Subject: [PATCH] char-device: spice_char_device_write_to_device: protect - against recursion - -This fixes Spice's smart card support and is related to -commit 697f3214fd16adcd524456003619f7f44ddd031b. - -Reported-by: Swapna Krishnan - -Recursion is now possible starting with spice_char_device_write_to_device -going through spice_char_device_wakeup (after going through qemu), -calling again to spice_char_device_write_to_device. - -The protecting code is the same as the one protecting the read path. - -This function call loop makes the program to abort with the following messages: - - usb-ccid: chardev: unexpected message of type 3000000 - qemu: qemu_mutex_lock: Resource deadlock avoided - -Backtrace: - -(gdb) bt -* #0 0x00007ffff3fc78c7 in raise () from /lib64/libc.so.6 -* #1 0x00007ffff3fc952a in abort () from /lib64/libc.so.6 -* #2 0x0000555555969a95 in error_exit (err=35, -* msg=0x5555559f8c90 <__func__.5119> "qemu_mutex_lock") -* at util/qemu-thread-posix.c:48 -* #3 0x0000555555969b82 in qemu_mutex_lock (mutex=0x5555562c4d60) -* at util/qemu-thread-posix.c:79 -* #4 0x0000555555714771 in qemu_chr_fe_write (s=0x5555562c4d60, -* buf=0x7fffffffd2a0 "", len=12) at qemu-char.c:219 -* #5 0x000055555586be49 in ccid_card_vscard_send_msg (s=0x5555565c5f80, -* type=VSC_Error, reader_id=0, payload=0x7fffffffd2e0 "", length=4) -* at hw/usb/ccid-card-passthru.c:75 -* #6 0x000055555586bf00 in ccid_card_vscard_send_error (s=0x5555565c5f80, -* reader_id=0, code=VSC_GENERAL_ERROR) at -* hw/usb/ccid-card-passthru.c:91 -* #7 0x000055555586c559 in ccid_card_vscard_handle_message ( -* card=0x5555565c5f80, scr_msg_header=0x5555565c6008) -* at hw/usb/ccid-card-passthru.c:254 -* #8 0x000055555586c72f in ccid_card_vscard_read (opaque=0x5555565c5f80, -* buf=0x5555565034b0 "", size=12) at hw/usb/ccid-card-passthru.c:289 -* #9 0x00005555557149db in qemu_chr_be_write (s=0x5555562c4d60, -* buf=0x5555565034b0 "", len=12) at qemu-char.c:305 -* #10 0x000055555571cde5 in vmc_write (sin=0x5555562c4e78, -* buf=0x5555565034b0 "", len=12) at spice-qemu-char.c:41 -* #11 0x00007ffff4fa86aa in spice_char_device_write_to_device ( -* dev=0x55555657f210) at char_device.c:462 -* #12 0x00007ffff4fa9b48 in spice_char_device_wakeup (dev=0x55555657f210) -* at char_device.c:862 -* #13 0x00007ffff4ff7658 in spice_server_char_device_wakeup -* (sin=0x5555562c4e78) at reds.c:2955 -* #14 0x000055555571d1d2 in spice_chr_write (chr=0x5555562c4d60, -* buf=0x7fffffffd560 "", len=12) at spice-qemu-char.c:189 -* #15 0x0000555555714789 in qemu_chr_fe_write (s=0x5555562c4d60, -* buf=0x7fffffffd560 "", len=12) at qemu-char.c:220 -* #16 0x000055555586be49 in ccid_card_vscard_send_msg (s=0x5555565c5f80, -* type=VSC_Error, reader_id=0, payload=0x7fffffffd5a0 "", length=4) -* at hw/usb/ccid-card-passthru.c:75 -* #17 0x000055555586bf00 in ccid_card_vscard_send_error -* (s=0x5555565c5f80, -* reader_id=0, code=VSC_SUCCESS) at hw/usb/ccid-card-passthru.c:91 -* #18 0x000055555586c4fc in ccid_card_vscard_handle_message ( -* card=0x5555565c5f80, scr_msg_header=0x5555565c6008) -* at hw/usb/ccid-card-passthru.c:242 -* #19 0x000055555586c72f in ccid_card_vscard_read (opaque=0x5555565c5f80, -* buf=0x5555565034b0 "", size=12) at hw/usb/ccid-card-passthru.c:289 -* #20 0x00005555557149db in qemu_chr_be_write (s=0x5555562c4d60, -* buf=0x5555565034b0 "", len=12) at qemu-char.c:305 -* #21 0x000055555571cde5 in vmc_write (sin=0x5555562c4e78, -* buf=0x5555565034b0 "", len=12) at spice-qemu-char.c:41 -* #22 0x00007ffff4fa86aa in spice_char_device_write_to_device ( -* dev=0x55555657f210) at char_device.c:462 -* #23 0x00007ffff4fa8d37 in spice_char_device_write_buffer_add ( -* dev=0x55555657f210, write_buf=0x555556501f70) at char_device.c:597 -* #24 0x00007ffff501142d in smartcard_channel_write_to_reader ( -* write_buf=0x555556501f70) at smartcard.c:669 -* #25 0x00007ffff501034c in smartcard_char_device_notify_reader_add ( -* st=0x55555657ef00) at smartcard.c:335 -* #26 0x00007ffff50112b3 in smartcard_add_reader (scc=0x555556493ee0, -* name=0x5555565023cc "E-Gate 0 0") at smartcard.c:642 -* #27 0x00007ffff50118d2 in smartcard_channel_handle_message ( -* rcc=0x555556493ee0, type=101, size=22, msg=0x5555565023c0 "\003") -* at smartcard.c:757 -* #28 0x00007ffff4fbc168 in red_peer_handle_incoming -* (stream=0x555556588250, handler=0x555556497ff0) at red_channel.c:308 -* #29 0x00007ffff4fbc231 in red_channel_client_receive -* (rcc=0x555556493ee0) at red_channel.c:326 -* #30 0x00007ffff4fc0019 in red_channel_client_event (fd=59, event=1, -* data=0x555556493ee0) at red_channel.c:1574 -* #31 0x00005555558b6076 in watch_read (opaque=0x5555565002f0) -* at ui/spice-core.c:101 -* #32 0x00005555558e8d48 in qemu_iohandler_poll (pollfds=0x5555562b7630, -* ret=2) at iohandler.c:143 -* #33 0x00005555558e89a4 in main_loop_wait (nonblocking=0) at -* main-loop.c:495 -* #34 0x00005555557219b0 in main_loop () at vl.c:1794 -* #35 0x0000555555729257 in main (argc=40, argv=0x7fffffffddc8, -* envp=0x7fffffffdf10) at vl.c:4350 - -(cherry picked from commit 0c1f5b00e7907aefee13f86a234558f00cd6c7ef) ---- - server/char_device.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/server/char_device.c b/server/char_device.c -index 285299c..e5d7c69 100644 ---- a/server/char_device.c -+++ b/server/char_device.c -@@ -64,6 +64,7 @@ struct SpiceCharDeviceState { - SpiceCharDeviceInstance *sin; - - int during_read_from_device; -+ int during_write_to_device; - - SpiceCharDeviceCallbacks cbs; - void *opaque; -@@ -441,6 +442,11 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - return 0; - } - -+ /* protect against recursion with spice_char_device_wakeup */ -+ if (dev->during_write_to_device++ > 0) { -+ return 0; -+ } -+ - spice_char_device_state_ref(dev); - - if (dev->write_to_dev_timer) { -@@ -465,6 +471,11 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - dev->cur_write_buf_pos; - n = sif->write(dev->sin, dev->cur_write_buf_pos, write_len); - if (n <= 0) { -+ if (dev->during_write_to_device > 1) { -+ dev->during_write_to_device = 1; -+ continue; /* a wakeup might have been called during the write - -+ make sure it doesn't get lost */ -+ } - break; - } - total += n; -@@ -489,6 +500,7 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev) - } - dev->active = dev->active || total; - } -+ dev->during_write_to_device = 0; - spice_char_device_state_unref(dev); - return total; - } diff --git a/SOURCES/0083-server-allows-to-set-maximum-monitors.patch b/SOURCES/0083-server-allows-to-set-maximum-monitors.patch deleted file mode 100644 index fa60289..0000000 --- a/SOURCES/0083-server-allows-to-set-maximum-monitors.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Fri, 19 Jun 2015 11:56:05 +0100 -Subject: [PATCH] server: allows to set maximum monitors - -spice-server will attempt to limit number of monitors. -Guest machine can send monitor list it accepts. Limiting the number sent -by guest will limit the number of monitors client will try to enable. -The guest usually see client monitors enabled and start using it so -not seeing client monitor won't try to enable more monitor. -In this case the additional monitor guest can support will always be -seen as heads with no attached monitors. -This allows limiting monitors number without changing guest drivers. - -Signed-off-by: Frediano Ziglio ---- - server/red_dispatcher.c | 10 ++++++++++ - server/red_dispatcher.h | 1 + - server/red_worker.c | 4 +++- - server/spice-server.syms | 5 +++++ - server/spice.h | 3 +++ - 5 files changed, 22 insertions(+), 1 deletion(-) - -diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c -index 6ecd3d4..6b395f4 100644 ---- a/server/red_dispatcher.c -+++ b/server/red_dispatcher.c -@@ -64,6 +64,7 @@ struct RedDispatcher { - Ring async_commands; - pthread_mutex_t async_lock; - QXLDevSurfaceCreate surface_create; -+ unsigned int max_monitors; - }; - - typedef struct RedWorkeState { -@@ -701,6 +702,7 @@ static void red_dispatcher_monitors_config_async(RedDispatcher *dispatcher, - payload.base.cmd = async_command_alloc(dispatcher, message, cookie); - payload.monitors_config = monitors_config; - payload.group_id = group_id; -+ payload.max_monitors = dispatcher->max_monitors; - - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); - } -@@ -995,6 +997,12 @@ void spice_qxl_monitors_config_async(QXLInstance *instance, QXLPHYSICAL monitors - } - - SPICE_GNUC_VISIBLE -+void spice_qxl_set_max_monitors(QXLInstance *instance, unsigned int max_monitors) -+{ -+ instance->st->dispatcher->max_monitors = MAX(1u, max_monitors); -+} -+ -+SPICE_GNUC_VISIBLE - void spice_qxl_driver_unload(QXLInstance *instance) - { - red_dispatcher_driver_unload(instance->st->dispatcher); -@@ -1116,6 +1124,8 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl) - red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; - red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; - -+ red_dispatcher->max_monitors = UINT_MAX; -+ - qxl->st->qif->get_init_info(qxl, &init_info); - - init_data.memslot_id_bits = init_info.memslot_id_bits; -diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h -index 7d23b11..bc4d620 100644 ---- a/server/red_dispatcher.h -+++ b/server/red_dispatcher.h -@@ -199,6 +199,7 @@ typedef struct RedWorkerMessageMonitorsConfigAsync { - RedWorkerMessageAsync base; - QXLPHYSICAL monitors_config; - int group_id; -+ unsigned int max_monitors; - } RedWorkerMessageMonitorsConfigAsync; - - typedef struct RedWorkerMessageDriverUnload { -diff --git a/server/red_worker.c b/server/red_worker.c -index dfa5274..64a7758 100644 ---- a/server/red_worker.c -+++ b/server/red_worker.c -@@ -11749,7 +11749,9 @@ static void handle_dev_monitors_config_async(void *opaque, void *payload) - /* TODO: raise guest bug (requires added QXL interface) */ - return; - } -- worker_update_monitors_config(worker, dev_monitors_config, count, max_allowed); -+ worker_update_monitors_config(worker, dev_monitors_config, -+ MIN(count, msg->max_monitors), -+ MIN(max_allowed, msg->max_monitors)); - red_worker_push_monitors_config(worker); - } - -diff --git a/server/spice-server.syms b/server/spice-server.syms -index 4f2dc37..59da512 100644 ---- a/server/spice-server.syms -+++ b/server/spice-server.syms -@@ -145,3 +145,8 @@ SPICE_SERVER_0.12.4 { - global: - spice_server_set_agent_file_xfer; - } SPICE_SERVER_0.12.3; -+ -+SPICE_SERVER_0.12.6 { -+global: -+ spice_qxl_set_max_monitors; -+} SPICE_SERVER_0.12.4; -diff --git a/server/spice.h b/server/spice.h -index 9c8e18a..3645775 100644 ---- a/server/spice.h -+++ b/server/spice.h -@@ -170,6 +170,9 @@ void spice_qxl_monitors_config_async(QXLInstance *instance, QXLPHYSICAL monitors - int group_id, uint64_t cookie); - /* since spice 0.12.3 */ - void spice_qxl_driver_unload(QXLInstance *instance); -+/* since spice 0.12.6 */ -+void spice_qxl_set_max_monitors(QXLInstance *instance, -+ unsigned int max_monitors); - - typedef struct QXLDrawArea { - uint8_t *buf; diff --git a/SOURCES/0084-Call-migrate_end_complete-after-falling-back-to-swit.patch b/SOURCES/0084-Call-migrate_end_complete-after-falling-back-to-swit.patch deleted file mode 100644 index b33d17a..0000000 --- a/SOURCES/0084-Call-migrate_end_complete-after-falling-back-to-swit.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 20 Jul 2016 17:16:31 +0400 -Subject: [PATCH] Call migrate_end_complete() after falling back to switch-host -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Eventually, during a seamless migration, qemu may finish to migrate -before the spice client even finished to connect all channels to -destination and informed the server. In this case, -main_channel_client_migrate_src_complete() will fall back to -switch-host method, and reds_mig_fill_wait_disconnect() is called to -complete the migration (disconnecting all channels). - -reds_mig_cleanup() is called when all channels are disconnected, but -reds->mig_wait_connect is still TRUE, and it will call -migrate_connect_complete() instead of the expected -migrate_end_complete(). Setting reds->mig_wait_connect to FALSE when -reds_mig_fill_wait_disconnect() solves the issue. - -Fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=1352836 - -Signed-off-by: Marc-André Lureau ---- - server/reds.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/server/reds.c b/server/reds.c -index e7e4090..9e1d5e7 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -3500,6 +3500,7 @@ static void reds_mig_fill_wait_disconnect(void) - wait_client->client = client; - ring_add(&reds->mig_wait_disconnect_clients, &wait_client->link); - } -+ reds->mig_wait_connect = FALSE; - reds->mig_wait_disconnect = TRUE; - core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT); - } diff --git a/SOURCES/0085-Prevent-possible-DoS-attempts-during-protocol-handsh.patch b/SOURCES/0085-Prevent-possible-DoS-attempts-during-protocol-handsh.patch deleted file mode 100644 index 38c9db7..0000000 --- a/SOURCES/0085-Prevent-possible-DoS-attempts-during-protocol-handsh.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 198ad1ea078c1b74c9e24617c509c6a408eb822e Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Mon, 28 Nov 2016 13:15:58 +0000 -Subject: [PATCH] Prevent possible DoS attempts during protocol handshake - -The limit for link message is specified using a 32 bit unsigned integer. -This could cause possible DoS due to excessive memory allocations and -some possible crashes. -For instance a value >= 2^31 causes a spice_assert to be triggered in -async_read_handler (reds-stream.c) due to an integer overflow at this -line: - - int n = async->end - async->now; - -This could be easily triggered with a program like - - #!/usr/bin/env python - - import socket - import time - from struct import pack - - server = '127.0.0.1' - port = 5900 - - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((server, port)) - data = pack('<4sIII', 'REDQ', 2, 2, 0xaaaaaaaa) - s.send(data) - - time.sleep(1) - -without requiring any authentication (the same can be done -with TLS). - -Signed-off-by: Frediano Ziglio ---- - server/reds.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/server/reds.c b/server/reds.c -index 9e1d5e7..1c215ed 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -2826,7 +2826,8 @@ static void reds_handle_read_header_done(void *opaque) - - reds->peer_minor_version = header->minor_version; - -- if (header->size < sizeof(SpiceLinkMess)) { -+ /* the check for 4096 is to avoid clients to cause arbitrary big memory allocations */ -+ if (header->size < sizeof(SpiceLinkMess) || header->size > 4096) { - reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); - spice_warning("bad size %u", header->size); - reds_link_free(link); --- -2.9.3 - diff --git a/SOURCES/0086-Prevent-integer-overflows-in-capability-checks.patch b/SOURCES/0086-Prevent-integer-overflows-in-capability-checks.patch deleted file mode 100644 index 83c914d..0000000 --- a/SOURCES/0086-Prevent-integer-overflows-in-capability-checks.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 665f7dddd2d534500d3b3e3e1f8135c49479ad25 Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Mon, 28 Nov 2016 13:15:58 +0000 -Subject: [PATCH] Prevent integer overflows in capability checks - -The limits for capabilities are specified using 32 bit unsigned integers. -This could cause possible integer overflows causing buffer overflows. -For instance the sum of num_common_caps and num_caps can be 0 avoiding -additional checks. -As the link message is now capped to 4096 and the capabilities are -contained in the link message, this commit limits the capabilities -to 1024 (capabilities are expressed in number of uint32_t items). - -Signed-off-by: Frediano Ziglio ---- - server/reds.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/server/reds.c b/server/reds.c -index 64f07cc..f5542f6 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -2744,6 +2744,14 @@ static void reds_handle_read_link_done(void *opaque) - uint32_t num_caps = link_mess->num_common_caps + link_mess->num_channel_caps; - int auth_selection; - -+ /* Prevent integer overflows. Currently we defined only 13 capabilities, -+ * I expect 1024 to be valid for quite a lot time */ -+ if (link_mess->num_channel_caps > 1024 || link_mess->num_common_caps > 1024) { -+ reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); -+ reds_link_free(link); -+ return; -+ } -+ - if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset > - link->link_header.size || - link_mess->caps_offset < sizeof(*link_mess))) { --- -2.9.3 - diff --git a/SOURCES/0087-main-channel-Prevent-overflow-reading-messages-from-.patch b/SOURCES/0087-main-channel-Prevent-overflow-reading-messages-from-.patch deleted file mode 100644 index a61dd04..0000000 --- a/SOURCES/0087-main-channel-Prevent-overflow-reading-messages-from-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c4e3113a8df53ba60c36829c8b2d583c2d5e529d Mon Sep 17 00:00:00 2001 -From: Frediano Ziglio -Date: Tue, 29 Nov 2016 16:46:56 +0000 -Subject: [PATCH] main-channel: Prevent overflow reading messages from client - -Caller is supposed the function return a buffer able to store -size bytes. - -Signed-off-by: Frediano Ziglio ---- - server/main_channel.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/server/main_channel.c b/server/main_channel.c -index 54718ba..bedff46 100644 ---- a/server/main_channel.c -+++ b/server/main_channel.c -@@ -1030,6 +1030,9 @@ static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, - - if (type == SPICE_MSGC_MAIN_AGENT_DATA) { - return reds_get_agent_data_buffer(mcc, size); -+ } else if (size > sizeof(main_chan->recv_buf)) { -+ /* message too large, caller will log a message and close the connection */ -+ return NULL; - } else { - return main_chan->recv_buf; - } --- -2.9.3 - diff --git a/SPECS/spice.spec b/SPECS/spice.spec index 86854af..40a708a 100644 --- a/SPECS/spice.spec +++ b/SPECS/spice.spec @@ -1,99 +1,16 @@ Name: spice -Version: 0.12.4 -Release: 20%{?dist} +Version: 0.12.8 +Release: 2%{?dist} Summary: Implements the SPICE protocol Group: User Interface/Desktops License: LGPLv2+ URL: http://www.spice-space.org/ Source0: http://www.spice-space.org/download/releases/%{name}-%{version}.tar.bz2 -Patch1: 0001-red_channel-prevent-adding-and-pushing-pipe-items-af.patch -Patch2: 0002-red_channel-add-ref-count-to-RedClient.patch -Patch3: 0003-main_dispatcher-add-ref-count-protection-to-RedClien.patch -Patch4: 0004-decouple-disconnection-of-the-main-channel-from-clie.patch -Patch5: 0005-reds-s-red_client_disconnect-red_channel_client_shut.patch -Patch6: 0006-snd_worker-fix-memory-leak-of-PlaybackChannel.patch -Patch7: 0007-snd_worker-snd_disconnect_channel-don-t-call-snd_cha.patch -Patch8: 0008-log-improve-debug-information-related-to-client-disc.patch -Patch9: 0009-red_worker-decrease-the-timeout-when-flushing-comman.patch -Patch10: 0010-Fix-buffer-overflow-when-decrypting-client-SPICE-tic.patch -Patch11: 0011-server-move-three-functions-to-red_channel.patch -Patch12: 0012-server-s-red_wait_all_sent-red_channel_wait_all_sent.patch -Patch13: 0013-red_worker-cleanup-red_clear_surface_drawables_from_.patch -Patch14: 0014-red_channel-cleanup-of-red_channel_client-blocking-m.patch -Patch15: 0015-red_worker-disconnect-the-channel-instead-of-shutdow.patch -Patch16: 0016-spice_timer_queue-don-t-call-timers-repeatedly.patch -Patch17: 0017-red_channel-add-on_input-callback-for-tracing-incomi.patch -Patch18: 0018-red_channel-add-option-to-monitor-whether-a-channel-.patch -Patch19: 0019-main_channel-monitoring-client-connection-status.patch -Patch20: 0020-Fix-crash-when-clearing-surface-memory.patch -Patch21: 0021-Fix-assert-in-mjpeg_encoder_adjust_params_to_bit_rat.patch -Patch22: 0022-reds-lookup-corresponding-channel-id.patch -Patch23: 0023-dispatcher-lower-a-monitor-config-warning-to-a-debug.patch -Patch24: 0024-mjpeg-Don-t-warn-on-unsupported-image-formats.patch -Patch25: 0025-server-Don-t-dump-the-bitmap-when-the-format-is-inva.patch -Patch26: 0026-Fix-Wunused-parameter.patch -Patch27: 0027-Fix-Wunused-value.patch -Patch28: 0028-Fix-Wsign.patch -Patch29: 0029-Fix-Wswitch.patch -Patch30: 0030-Fix-Wformat.patch -Patch31: 0031-Fix-Wnonnull.patch -Patch32: 0032-Fix-Wmissing-field-initializers.patch -Patch33: 0033-Fix-Wunused-function.patch -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-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 -Patch65: 0065-smartcard-add-a-ref-to-item-before-adding-to-pipe.patch -Patch66: 0066-smartcard-allocate-msg-with-the-expected-size.patch -Patch67: 0067-create-a-function-to-validate-surface-parameters.patch -Patch68: 0068-improve-primary-surface-parameter-checks.patch -Patch69: 0069-reds-Do-not-abort-due-to-wrong-header.patch -Patch70: 0070-memslot-do-not-crash-if-guest-provide-a-wrong-addres.patch -Patch71: 0071-red-channel-make-red_client_-ref-unref-thread-safe.patch -Patch72: 0072-chardev-remove-write-polling.patch -Patch73: 0073-clean-up-remove-unused-function.patch -Patch74: 0074-Remove-guest-side-video-time-stamping.patch -Patch75: 0075-char-device-fix-usage-of-free-unref-on-WriteBuffer.patch -Patch76: 0076-spicevmc-set-state-of-DeviceInstance-to-NULL.patch -Patch77: 0077-char-device-set-to-NULL-freed-pointers-on-destroy.patch -Patch78: 0078-channel-add-option-tcp-keepalive-timeout-to-channels.patch -Patch79: 0079-Always-enable-TCP-keepalive.patch -Patch80: 0080-Remove-spice_server_set_keepalive_timeout.patch -Patch81: 0081-sound-do-not-modify-client-state-on-migration.patch -Patch82: 0082-char-device-spice_char_device_write_to_device-protec.patch -Patch83: 0083-server-allows-to-set-maximum-monitors.patch -Patch84: 0084-Call-migrate_end_complete-after-falling-back-to-swit.patch -Patch85: 0085-Prevent-possible-DoS-attempts-during-protocol-handsh.patch -Patch86: 0086-Prevent-integer-overflows-in-capability-checks.patch -Patch87: 0087-main-channel-Prevent-overflow-reading-messages-from-.patch - +Patch01: 0001-Call-migrate_end_complete-after-falling-back-to-swit.patch +Patch02: 0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch +Patch03: 0003-Prevent-integer-overflows-in-capability-checks.patch +Patch04: 0004-main-channel-Prevent-overflow-reading-messages-from-.patch +Patch05: 0005-reds-Check-link-header-magic-without-waiting-for-the.patch # https://bugzilla.redhat.com/show_bug.cgi?id=613529 %if 0%{?rhel} @@ -104,7 +21,7 @@ ExclusiveArch: i686 x86_64 armv6l armv7l armv7hl BuildRequires: pkgconfig BuildRequires: glib2-devel >= 2.22 -# BuildRequires: spice-protocol >= 0.12.3 -- not needed since spice-0.11.3 +BuildRequires: spice-protocol >= 0.12.10 BuildRequires: celt051-devel BuildRequires: pixman-devel alsa-lib-devel openssl-devel libjpeg-turbo-devel BuildRequires: libcacard-devel cyrus-sasl-devel @@ -180,6 +97,15 @@ mkdir -p %{buildroot}%{_libexecdir} %changelog +* Tue Apr 25 2017 Christophe Fergeau 0.12.8-2 +- Drop clients immediatly if the magic they send is wrong + Resolves: rhbz#1416692 + +* Mon Jan 16 2017 Christophe Fergeau 0.12.8-1 +- Rebase to spice-server 0.12.8 + Resolves: rhbz#1388947 + Resolves: rhbz#1377551 + Resolves: rhbz#1283202 * Fri Dec 09 2016 Frediano Ziglio - 0.12.4-20 - Fix buffer overflow in main_channel_alloc_msg_rcv_buf when reading large messages.