[Spice-devel] [PATCH 3/3] channel: make sure we retain RedChannelClient while processing it

Jonathon Jongsma jjongsma at redhat.com
Thu Dec 10 09:24:00 PST 2015


On Wed, 2015-12-09 at 13:36 +0000, Frediano Ziglio wrote:
> During display_channel_handle_migrate_data the pointer is passed
> to different functions which could release it making the pointer
> invalid. Make sure pointer is not freed while processing.

Maybe I didn't go down every path, but I didn't see any cases where the channel
client is freed during processing. But regardless, I'd say it's a good idea to
maintain a reference during processing.

Acked-by: Jonathon Jongsma <jjongsma at redhat.com>


> 
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  server/display-channel.c | 8 ++++++--
>  server/red-channel.c     | 6 ++----
>  server/red-channel.h     | 2 ++
>  3 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/server/display-channel.c b/server/display-channel.c
> index 6b1043b..fe05121 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -1204,6 +1204,7 @@ int display_channel_handle_migrate_data(DisplayChannel
> *display)
>      uint64_t end_time = red_get_monotonic_time() +
> DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT;
>      RedChannel *channel = &display->common.base;
>      RedChannelClient *rcc;
> +    int ret = FALSE;
>  
>      if (!red_channel_is_waiting_for_migrate_data(&display->common.base)) {
>          return FALSE;
> @@ -1214,6 +1215,7 @@ int display_channel_handle_migrate_data(DisplayChannel
> *display)
>  
>      rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients),
> RedChannelClient, channel_link);
>  
> +    red_channel_client_ref(rcc);
>      for (;;) {
>          red_channel_client_receive(rcc);
>          if (!red_channel_client_is_connected(rcc)) {
> @@ -1221,7 +1223,8 @@ int display_channel_handle_migrate_data(DisplayChannel
> *display)
>          }
>  
>          if (!red_channel_client_is_waiting_for_migrate_data(rcc)) {
> -            return TRUE;
> +            ret = TRUE;
> +            break;
>          }
>          if (red_get_monotonic_time() > end_time) {
>              spice_warning("timeout");
> @@ -1230,7 +1233,8 @@ int display_channel_handle_migrate_data(DisplayChannel
> *display)
>          }
>          usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
>      }
> -    return FALSE;
> +    red_channel_client_unref(rcc);
> +    return ret;
>  }
>  
>  void display_channel_flush_all_surfaces(DisplayChannel *display)
> diff --git a/server/red-channel.c b/server/red-channel.c
> index 4b1d426..7dfb9bf 100644
> --- a/server/red-channel.c
> +++ b/server/red-channel.c
> @@ -116,8 +116,6 @@ static inline int
> red_channel_client_waiting_for_ack(RedChannelClient *rcc);
>  */
>  static void red_channel_ref(RedChannel *channel);
>  static void red_channel_unref(RedChannel *channel);
> -static void red_channel_client_ref(RedChannelClient *rcc);
> -static void red_channel_client_unref(RedChannelClient *rcc);
>  
>  static uint32_t full_header_get_msg_size(SpiceDataHeaderOpaque *header)
>  {
> @@ -1231,12 +1229,12 @@ static void red_channel_unref(RedChannel *channel)
>      }
>  }
>  
> -static void red_channel_client_ref(RedChannelClient *rcc)
> +void red_channel_client_ref(RedChannelClient *rcc)
>  {
>      rcc->refs++;
>  }
>  
> -static void red_channel_client_unref(RedChannelClient *rcc)
> +void red_channel_client_unref(RedChannelClient *rcc)
>  {
>      if (!--rcc->refs) {
>          spice_debug("destroy rcc=%p", rcc);
> diff --git a/server/red-channel.h b/server/red-channel.h
> index 8206cec..2058350 100644
> --- a/server/red-channel.h
> +++ b/server/red-channel.h
> @@ -418,6 +418,8 @@ int red_channel_is_waiting_for_migrate_data(RedChannel
> *channel);
>  
>  void red_channel_client_destroy(RedChannelClient *rcc);
>  void red_channel_destroy(RedChannel *channel);
> +void red_channel_client_ref(RedChannelClient *rcc);
> +void red_channel_client_unref(RedChannelClient *rcc);
>  
>  int red_channel_client_test_remote_common_cap(RedChannelClient *rcc, uint32_t
> cap);
>  int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap);


More information about the Spice-devel mailing list