[Spice-commits] server/red-channel.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Tue Jan 19 16:32:42 PST 2016


 server/red-channel.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

New commits:
commit ddaa46d70fb633750e16658779c6cc570a10e058
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Tue Jan 19 10:35:48 2016 +0000

    channel: do not free rcc->stream in red_channel_client_disconnect
    
    This fixes a crash if red_channel_client disconnect is called
    handling a message.
    This can happen for instance while handling SPICE_MSGC_ACK which calls
    red_channel_client_push which tries to detect write errors while writing
    to a socket (for instance socket disconnection).
    Messages are read in a loop and red_channel_client_disconnect would
    cause rcc->stream to be NULL which will result in a use-after-free
    problem (stream in red_peer_handle_incoming will use cached stream value).
    
    Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/red-channel.c b/server/red-channel.c
index 306c87d..efe889a 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -1233,6 +1233,10 @@ void red_channel_client_unref(RedChannelClient *rcc)
 {
     if (!--rcc->refs) {
         spice_debug("destroy rcc=%p", rcc);
+
+        reds_stream_free(rcc->stream);
+        rcc->stream = NULL;
+
         if (rcc->send_data.main.marshaller) {
             spice_marshaller_destroy(rcc->send_data.main.marshaller);
         }
@@ -1749,7 +1753,7 @@ void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
 int red_channel_client_is_connected(RedChannelClient *rcc)
 {
     if (!rcc->dummy) {
-        return rcc->stream != NULL;
+        return ring_item_is_linked(&rcc->channel_link);
     } else {
         return rcc->dummy_connected;
     }
@@ -1804,6 +1808,8 @@ static void red_channel_remove_client(RedChannelClient *rcc)
                       rcc->channel->type, rcc->channel->id,
                       rcc->channel->thread_id, pthread_self());
     }
+    spice_return_if_fail(ring_item_is_linked(&rcc->channel_link));
+
     ring_remove(&rcc->channel_link);
     spice_assert(rcc->channel->clients_num > 0);
     rcc->channel->clients_num--;
@@ -1845,8 +1851,6 @@ void red_channel_client_disconnect(RedChannelClient *rcc)
         rcc->channel->core->watch_remove(rcc->stream->watch);
         rcc->stream->watch = NULL;
     }
-    reds_stream_free(rcc->stream);
-    rcc->stream = NULL;
     if (rcc->latency_monitor.timer) {
         rcc->channel->core->timer_remove(rcc->latency_monitor.timer);
         rcc->latency_monitor.timer = NULL;


More information about the Spice-commits mailing list