diff options
Diffstat (limited to '0001-vnc-Drop-frames-if-client-is-gone.patch')
-rw-r--r-- | 0001-vnc-Drop-frames-if-client-is-gone.patch | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/0001-vnc-Drop-frames-if-client-is-gone.patch b/0001-vnc-Drop-frames-if-client-is-gone.patch new file mode 100644 index 0000000..59dde2a --- /dev/null +++ b/0001-vnc-Drop-frames-if-client-is-gone.patch @@ -0,0 +1,80 @@ +From ab97841629f5f3f4fab9993b6255b6ae04828b9c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com> +Date: Wed, 9 Sep 2020 10:14:20 +0200 +Subject: [PATCH] vnc: Drop frames if client is gone + +Frames from PipeWire are posted asynchronously from a I/O thread to the +main thread where they are turned into VNC frame updates and cursor +movements. On the other hand, sessions are closed asynchronously when +the VNC client disappears. If a frame ended up on the main thread after +a client disappeared but before the session and stream was closed, we'd +try to turn the new frames into VNC updates without a client being +available, causing use after free. + +Fix this by dropping frames that happens during this time frame. + +Closes: https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/issues/43 +--- + src/grd-session-vnc.c | 7 +++++++ + src/grd-session-vnc.h | 2 ++ + src/grd-vnc-pipewire-stream.c | 8 ++++++++ + 3 files changed, 17 insertions(+) + +diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c +index 813838a..a06d34d 100644 +--- a/src/grd-session-vnc.c ++++ b/src/grd-session-vnc.c +@@ -209,6 +209,12 @@ maybe_queue_close_session_idle (GrdSessionVnc *session_vnc) + g_idle_add (close_session_idle, session_vnc); + } + ++gboolean ++grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc) ++{ ++ return !session_vnc->rfb_client; ++} ++ + static void + handle_client_gone (rfbClientPtr rfb_client) + { +@@ -218,6 +224,7 @@ handle_client_gone (rfbClientPtr rfb_client) + + grd_session_vnc_detach_source (session_vnc); + maybe_queue_close_session_idle (session_vnc); ++ session_vnc->rfb_client = NULL; + } + + static void +diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h +index 579a12a..07678c8 100644 +--- a/src/grd-session-vnc.h ++++ b/src/grd-session-vnc.h +@@ -57,4 +57,6 @@ void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc, + + int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc); + ++gboolean grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc); ++ + #endif /* GRD_SESSION_VNC_H */ +diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c +index 78793c4..96dd7c9 100644 +--- a/src/grd-vnc-pipewire-stream.c ++++ b/src/grd-vnc-pipewire-stream.c +@@ -234,6 +234,14 @@ do_render (struct spa_loop *loop, + if (!frame) + return 0; + ++ if (grd_session_vnc_is_client_gone (stream->session)) ++ { ++ g_free (frame->data); ++ g_clear_pointer (&frame->rfb_cursor, rfbFreeCursor); ++ g_free (frame); ++ return 0; ++ } ++ + if (frame->rfb_cursor) + grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor); + +-- +2.26.2 + |