diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/.gitignore b/.gitignore index a59cc2b..586a68d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/gnome-remote-desktop-0.1.*.tar.xz +/gnome-remote-desktop-*.tar.xz +/gnome-remote-desktop-*-build diff --git a/0001-meson.build-Bump-pipewire-requirement-to-0.2.2.patch b/0001-meson.build-Bump-pipewire-requirement-to-0.2.2.patch deleted file mode 100644 index 62b84b2..0000000 --- a/0001-meson.build-Bump-pipewire-requirement-to-0.2.2.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 8f760d73df6011330cd09da7ca7b8a3f40c9a3ef Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Tue, 7 Aug 2018 13:35:43 +0200 -Subject: [PATCH] meson.build: Bump pipewire requirement to 0.2.2 - ---- - meson.build | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/meson.build b/meson.build -index 6951b89..34ec5ea 100644 ---- a/meson.build -+++ b/meson.build -@@ -10,7 +10,7 @@ gnome = import('gnome') - glib_dep = dependency('glib-2.0') - gio_dep = dependency('gio-2.0') - gio_unix_dep = dependency('gio-unix-2.0') --pipewire_dep = dependency('libpipewire-0.1') -+pipewire_dep = dependency('libpipewire-0.2', version: '>= 0.2.2') - systemd_dep = dependency('systemd') - libvncserver_dep = dependency('libvncserver') - libsecret_dep = dependency('libsecret-1') --- -2.17.1 - diff --git a/0001-session-vnc-Don-t-requeue-close-session-idle.patch b/0001-session-vnc-Don-t-requeue-close-session-idle.patch deleted file mode 100644 index 20a3f56..0000000 --- a/0001-session-vnc-Don-t-requeue-close-session-idle.patch +++ /dev/null @@ -1,84 +0,0 @@ -From add0ea34fd1d6835c99aebeb4e56b805b38e53ec Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Mon, 1 Oct 2018 18:02:39 +0200 -Subject: [PATCH 1/2] session/vnc: Don't requeue close session idle - -If being closed due to a PipeWire error, RFB will still process state -and invoke callbacks when cleaning up the RFB screen, meaning we'd -requeue the close session idle handler. Avoid this by avoiding -requeueing if there is already one queued, and don't mark is as unqueued -until after actually stopping the session. ---- - src/grd-session-vnc.c | 28 ++++++++++++++++++---------- - 1 file changed, 18 insertions(+), 10 deletions(-) - -diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index ce4dd29..3c98eeb 100644 ---- a/src/grd-session-vnc.c -+++ b/src/grd-session-vnc.c -@@ -165,6 +165,16 @@ grd_session_vnc_draw_buffer (GrdSessionVnc *session_vnc, - rfbProcessEvents (session_vnc->rfb_screen, 0); - } - -+static void -+maybe_queue_close_session_idle (GrdSessionVnc *session_vnc) -+{ -+ if (session_vnc->close_session_idle_id) -+ return; -+ -+ session_vnc->close_session_idle_id = -+ g_idle_add (close_session_idle, session_vnc); -+} -+ - static void - handle_client_gone (rfbClientPtr rfb_client) - { -@@ -172,8 +182,7 @@ handle_client_gone (rfbClientPtr rfb_client) - - g_debug ("VNC client gone"); - -- session_vnc->close_session_idle_id = -- g_idle_add (close_session_idle, session_vnc); -+ maybe_queue_close_session_idle (session_vnc); - } - - static void -@@ -670,12 +679,6 @@ grd_session_vnc_stop (GrdSession *session) - - g_debug ("Stopping VNC session"); - -- if (session_vnc->close_session_idle_id) -- { -- g_source_remove (session_vnc->close_session_idle_id); -- session_vnc->close_session_idle_id = 0; -- } -- - g_clear_object (&session_vnc->pipewire_stream); - - grd_session_vnc_detach_source (session_vnc); -@@ -683,6 +686,12 @@ grd_session_vnc_stop (GrdSession *session) - g_clear_object (&session_vnc->connection); - g_clear_pointer (&session_vnc->rfb_screen->frameBuffer, g_free); - g_clear_pointer (&session_vnc->rfb_screen, (GDestroyNotify) rfbScreenCleanup); -+ -+ if (session_vnc->close_session_idle_id) -+ { -+ g_source_remove (session_vnc->close_session_idle_id); -+ session_vnc->close_session_idle_id = 0; -+ } - } - - static gboolean -@@ -703,8 +712,7 @@ on_pipwire_stream_closed (GrdVncPipeWireStream *stream, - { - g_warning ("PipeWire stream closed, closing client"); - -- session_vnc->close_session_idle_id = -- g_idle_add (close_session_idle, session_vnc); -+ maybe_queue_close_session_idle (session_vnc); - } - - static void --- -2.17.1 - diff --git a/0001-vnc-Drop-frames-if-client-is-gone.patch b/0001-vnc-Drop-frames-if-client-is-gone.patch deleted file mode 100644 index 2ce0d97..0000000 --- a/0001-vnc-Drop-frames-if-client-is-gone.patch +++ /dev/null @@ -1,81 +0,0 @@ -From e607efe6584cffc3284776e5795af05bd28da10d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -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 -(cherry picked from commit ab97841629f5f3f4fab9993b6255b6ae04828b9c) ---- - 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 21735bf..3a8852d 100644 ---- a/src/grd-session-vnc.c -+++ b/src/grd-session-vnc.c -@@ -219,6 +219,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) - { -@@ -229,6 +235,7 @@ handle_client_gone (rfbClientPtr rfb_client) - grd_session_vnc_pause (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 a065857..ffd8653 100644 ---- a/src/grd-session-vnc.h -+++ b/src/grd-session-vnc.h -@@ -76,4 +76,6 @@ void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc); - - GrdVncServer * grd_session_vnc_get_vnc_server (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 1feaef1..71357f0 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -287,6 +287,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 - diff --git a/0001-vnc-pipewire-stream-Handle-stride-mismatch.patch b/0001-vnc-pipewire-stream-Handle-stride-mismatch.patch deleted file mode 100644 index 536634c..0000000 --- a/0001-vnc-pipewire-stream-Handle-stride-mismatch.patch +++ /dev/null @@ -1,221 +0,0 @@ -From b38d39072dd34e1128b1d43c0d692606311d5753 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Thu, 7 May 2020 15:48:22 +0200 -Subject: [PATCH 1/6] vnc/pipewire-stream: Handle stride mismatch - -The VNC server framebuffer assumes a particular stride; but there is no -guarantee that we'll get the same from PipeWire. Handle this gracefully -by coping row by row instead of the whole buffer. ---- - src/grd-vnc-pipewire-stream.c | 23 +++++++++++++++-------- - 1 file changed, 15 insertions(+), 8 deletions(-) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index 88c07be..261292a 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -160,84 +160,77 @@ on_stream_state_changed (void *user_data, - enum pw_stream_state state, - const char *error) - { - g_debug ("Pipewire stream state changed from %s to %s", - pw_stream_state_as_string (old), - pw_stream_state_as_string (state)); - - switch (state) - { - case PW_STREAM_STATE_ERROR: - g_warning ("PipeWire stream error: %s", error); - break; - case PW_STREAM_STATE_PAUSED: - case PW_STREAM_STATE_STREAMING: - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: - break; - } - } - - static void - on_stream_param_changed (void *user_data, - uint32_t id, - const struct spa_pod *format) - { - GrdVncPipeWireStream *stream = GRD_VNC_PIPEWIRE_STREAM (user_data); - uint8_t params_buffer[1024]; - struct spa_pod_builder pod_builder; - int width; - int height; -- int stride; -- int size; - const struct spa_pod *params[3]; - - if (!format || id != SPA_PARAM_Format) - return; - - spa_format_video_raw_parse (format, &stream->spa_format); - - pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer)); - - width = stream->spa_format.size.width; - height = stream->spa_format.size.height; - - grd_session_vnc_queue_resize_framebuffer (stream->session, width, height); - -- stride = grd_session_vnc_get_framebuffer_stride (stream->session); -- size = stride * height; -- - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, -- SPA_PARAM_BUFFERS_size, SPA_POD_Int (size), -- SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride), - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (8, 1, 8), - 0); - - params[1] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, - SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Header), - SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header)), - 0); - - params[2] = spa_pod_builder_add_object( - &pod_builder, - SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, - SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor), - SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE (64,64), - CURSOR_META_SIZE (1,1), - CURSOR_META_SIZE (256,256)), - 0); - - pw_stream_update_params (stream->pipewire_stream, - params, G_N_ELEMENTS (params)); - } - - static gboolean - spa_pixel_format_to_grd_pixel_format (uint32_t spa_format, - GrdPixelFormat *out_format) - { - if (spa_format == SPA_VIDEO_FORMAT_RGBA) - *out_format = GRD_PIXEL_FORMAT_RGBA8888; - else -@@ -292,101 +285,115 @@ do_render (struct spa_loop *loop, - g_mutex_unlock (&stream->frame_mutex); - - if (!frame) - return 0; - - if (frame->rfb_cursor) - grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor); - - if (frame->cursor_moved) - { - grd_session_vnc_move_cursor (stream->session, - frame->cursor_x, - frame->cursor_y); - } - - if (frame->data) - grd_session_vnc_take_buffer (stream->session, frame->data); - - g_free (frame); - - return 0; - } - - static GrdVncFrame * - process_buffer (GrdVncPipeWireStream *stream, - struct spa_buffer *buffer) - { - size_t size; - uint8_t *map; - void *src_data; -+ int src_stride; -+ int dst_stride; -+ int height; -+ int y; - struct spa_meta_cursor *spa_meta_cursor; - g_autofree GrdVncFrame *frame = NULL; - - frame = g_new0 (GrdVncFrame, 1); - - if (buffer->datas[0].chunk->size == 0) - { - size = 0; - map = NULL; - src_data = NULL; - } - else if (buffer->datas[0].type == SPA_DATA_MemFd) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) - { - int fd; - - fd = buffer->datas[0].fd; - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - sync_dma_buf (fd, DMA_BUF_SYNC_START); - - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_MemPtr) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = NULL; - src_data = buffer->datas[0].data; - } - else - { - return NULL; - } - -- frame->data = g_memdup (src_data, buffer->datas[0].maxsize); -+ src_stride = buffer->datas[0].chunk->stride; -+ dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session); -+ height = stream->spa_format.size.height; -+ -+ frame->data = g_malloc (height * dst_stride); -+ for (y = 0; y < height; y++) -+ { -+ memcpy (((uint8_t *) frame->data) + y * dst_stride, -+ ((uint8_t *) src_data) + y * src_stride, -+ dst_stride); -+ } - - if (map) - { - if (buffer->datas[0].type == SPA_DATA_DmaBuf) - sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END); - munmap (map, size); - } - - spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor, - sizeof *spa_meta_cursor); - if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor)) - { - struct spa_meta_bitmap *spa_meta_bitmap; - GrdPixelFormat format; - - if (spa_meta_cursor->bitmap_offset) - { - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - } - else - { - spa_meta_bitmap = NULL; - } - - if (spa_meta_bitmap && - spa_meta_bitmap->size.width > 0 && - spa_meta_bitmap->size.height > 0 && - spa_pixel_format_to_grd_pixel_format (spa_meta_bitmap->format, --- -2.26.2 - diff --git a/0002-vnc-pipewire-stream-Close-session-when-disconnected.patch b/0002-vnc-pipewire-stream-Close-session-when-disconnected.patch deleted file mode 100644 index cd1c5e4..0000000 --- a/0002-vnc-pipewire-stream-Close-session-when-disconnected.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 59188d81cf8936cd9f5400df040d875427251bf2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Mon, 1 Oct 2018 18:05:07 +0200 -Subject: [PATCH 2/2] vnc-pipewire-stream: Close session when disconnected - -When there is an active stream, and we're disconnected from PipeWire -(e.g. because it terminated), close the session. ---- - src/grd-vnc-pipewire-stream.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index 66d66a0..d6454b8 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -392,6 +392,9 @@ on_state_changed (void *user_data, - } - break; - case PW_REMOTE_STATE_UNCONNECTED: -+ if (stream->pipewire_stream) -+ g_signal_emit (stream, signals[CLOSED], 0); -+ break; - case PW_REMOTE_STATE_CONNECTING: - break; - } --- -2.17.1 - diff --git a/0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch b/0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch deleted file mode 100644 index d33318a..0000000 --- a/0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 685bdbbcc909fa3beb5a4c910befcd1f44131bc3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 3 Jul 2020 17:12:58 +0200 -Subject: [PATCH 2/6] vnc-pipewire-stream: Properly process cursor-change-only - frames - -Such frames will have the buffer data size set to 0, as it is empty, but -may contain metadata carrying the cursor update. ---- - src/grd-vnc-pipewire-stream.c | 31 +++++++++++++++++-------------- - 1 file changed, 17 insertions(+), 14 deletions(-) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index 261292a..763f5eb 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -285,114 +285,117 @@ do_render (struct spa_loop *loop, - g_mutex_unlock (&stream->frame_mutex); - - if (!frame) - return 0; - - if (frame->rfb_cursor) - grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor); - - if (frame->cursor_moved) - { - grd_session_vnc_move_cursor (stream->session, - frame->cursor_x, - frame->cursor_y); - } - - if (frame->data) - grd_session_vnc_take_buffer (stream->session, frame->data); - - g_free (frame); - - return 0; - } - - static GrdVncFrame * - process_buffer (GrdVncPipeWireStream *stream, - struct spa_buffer *buffer) - { - size_t size; - uint8_t *map; - void *src_data; -- int src_stride; -- int dst_stride; -- int height; -- int y; - struct spa_meta_cursor *spa_meta_cursor; - g_autofree GrdVncFrame *frame = NULL; - - frame = g_new0 (GrdVncFrame, 1); - - if (buffer->datas[0].chunk->size == 0) - { -- size = 0; - map = NULL; - src_data = NULL; - } - else if (buffer->datas[0].type == SPA_DATA_MemFd) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) - { - int fd; - - fd = buffer->datas[0].fd; - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - sync_dma_buf (fd, DMA_BUF_SYNC_START); - - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_MemPtr) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = NULL; - src_data = buffer->datas[0].data; - } - else - { - return NULL; - } - -- src_stride = buffer->datas[0].chunk->stride; -- dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session); -- height = stream->spa_format.size.height; -- -- frame->data = g_malloc (height * dst_stride); -- for (y = 0; y < height; y++) -+ if (src_data) - { -- memcpy (((uint8_t *) frame->data) + y * dst_stride, -- ((uint8_t *) src_data) + y * src_stride, -- dst_stride); -+ int src_stride; -+ int dst_stride; -+ int height; -+ int y; -+ -+ src_stride = buffer->datas[0].chunk->stride; -+ dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session); -+ height = stream->spa_format.size.height; -+ -+ frame->data = g_malloc (height * dst_stride); -+ for (y = 0; y < height; y++) -+ { -+ memcpy (((uint8_t *) frame->data) + y * dst_stride, -+ ((uint8_t *) src_data) + y * src_stride, -+ dst_stride); -+ } - } - - if (map) - { - if (buffer->datas[0].type == SPA_DATA_DmaBuf) - sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END); - munmap (map, size); - } - - spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor, - sizeof *spa_meta_cursor); - if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor)) - { - struct spa_meta_bitmap *spa_meta_bitmap; - GrdPixelFormat format; - - if (spa_meta_cursor->bitmap_offset) - { - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - } - else - { - spa_meta_bitmap = NULL; - } - - if (spa_meta_bitmap && - spa_meta_bitmap->size.width > 0 && - spa_meta_bitmap->size.height > 0 && --- -2.26.2 - diff --git a/0003-session-vnc-Add-API-to-flush.patch b/0003-session-vnc-Add-API-to-flush.patch deleted file mode 100644 index f512b12..0000000 --- a/0003-session-vnc-Add-API-to-flush.patch +++ /dev/null @@ -1,149 +0,0 @@ -From def96b6f225636b3b9edf1993ca2e1ba9ed82f30 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 3 Jul 2020 17:03:52 +0200 -Subject: [PATCH 3/6] session-vnc: Add API to flush - -When no damage is to be reported, but e.g. cursor moved, we need to -flush, so add API to make this possible. ---- - src/grd-session-vnc.c | 6 ++++++ - src/grd-session-vnc.h | 2 ++ - 2 files changed, 8 insertions(+) - -diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index a93a2e3..21735bf 100644 ---- a/src/grd-session-vnc.c -+++ b/src/grd-session-vnc.c -@@ -152,60 +152,66 @@ grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc, - if (session_vnc->rfb_client->preferredEncoding == -1) - { - session_vnc->pending_framebuffer_resize = TRUE; - session_vnc->pending_framebuffer_width = width; - session_vnc->pending_framebuffer_height = height; - return; - } - - resize_vnc_framebuffer (session_vnc, width, height); - } - - void - grd_session_vnc_take_buffer (GrdSessionVnc *session_vnc, - void *data) - { - if (session_vnc->pending_framebuffer_resize) - { - free (data); - return; - } - - free (session_vnc->rfb_screen->frameBuffer); - session_vnc->rfb_screen->frameBuffer = data; - - rfbMarkRectAsModified (session_vnc->rfb_screen, 0, 0, - session_vnc->rfb_screen->width, - session_vnc->rfb_screen->height); - rfbProcessEvents (session_vnc->rfb_screen, 0); - } - -+void -+grd_session_vnc_flush (GrdSessionVnc *session_vnc) -+{ -+ rfbProcessEvents (session_vnc->rfb_screen, 0); -+} -+ - void - grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc, - rfbCursorPtr rfb_cursor) - { - rfbSetCursor (session_vnc->rfb_screen, rfb_cursor); - } - - void - grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc, - int x, - int y) - { - if (session_vnc->rfb_screen->cursorX == x || - session_vnc->rfb_screen->cursorY == y) - return; - - LOCK (session_vnc->rfb_screen->cursorMutex); - session_vnc->rfb_screen->cursorX = x; - session_vnc->rfb_screen->cursorY = y; - UNLOCK (session_vnc->rfb_screen->cursorMutex); - - session_vnc->rfb_client->cursorWasMoved = TRUE; - } - - static void - maybe_queue_close_session_idle (GrdSessionVnc *session_vnc) - { - if (session_vnc->close_session_idle_id) - return; - -diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h -index 294860e..a065857 100644 ---- a/src/grd-session-vnc.h -+++ b/src/grd-session-vnc.h -@@ -22,56 +22,58 @@ - - #ifndef GRD_SESSION_VNC_H - #define GRD_SESSION_VNC_H - - #include - #include - #include - - #include "grd-session.h" - #include "grd-types.h" - - #define GRD_TYPE_SESSION_VNC (grd_session_vnc_get_type ()) - G_DECLARE_FINAL_TYPE (GrdSessionVnc, - grd_session_vnc, - GRD, SESSION_VNC, - GrdSession); - - typedef gboolean (* GrdVncSocketGrabFunc) (GrdSessionVnc *session_vnc, - GError **error); - - GrdSessionVnc *grd_session_vnc_new (GrdVncServer *vnc_server, - GSocketConnection *connection); - - void grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc, - int width, - int height); - - void grd_session_vnc_take_buffer (GrdSessionVnc *session_vnc, - void *data); - -+void grd_session_vnc_flush (GrdSessionVnc *session_vnc); -+ - void grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc, - rfbCursorPtr rfb_cursor); - - void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc, - int x, - int y); - - int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc); - - int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc); - - rfbClientPtr grd_session_vnc_get_rfb_client (GrdSessionVnc *session_vnc); - - void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, - GrdVncSocketGrabFunc grab_func); - - void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc, - GrdVncSocketGrabFunc grab_func); - - gboolean grd_session_vnc_is_paused (GrdSessionVnc *session_vnc); - - void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc); - - GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc); - - #endif /* GRD_SESSION_VNC_H */ --- -2.26.2 - diff --git a/0004-vnc-pipewire-stream-Flush-connection-if-no-new-pixel.patch b/0004-vnc-pipewire-stream-Flush-connection-if-no-new-pixel.patch deleted file mode 100644 index fa52082..0000000 --- a/0004-vnc-pipewire-stream-Flush-connection-if-no-new-pixel.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 8c92fe8bc6c3003aacdfd96fed2d82bc542f3f27 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 3 Jul 2020 17:13:58 +0200 -Subject: [PATCH 4/6] vnc-pipewire-stream: Flush connection if no new pixel - buffer - -Otherwise we'll wait on input until we flush out our new cursor move -only output. ---- - src/grd-vnc-pipewire-stream.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index 763f5eb..ec23b0a 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -272,60 +272,62 @@ sync_dma_buf (int fd, - static int - do_render (struct spa_loop *loop, - bool async, - uint32_t seq, - const void *data, - size_t size, - void *user_data) - { - GrdVncPipeWireStream *stream = GRD_VNC_PIPEWIRE_STREAM (user_data); - GrdVncFrame *frame; - - g_mutex_lock (&stream->frame_mutex); - frame = g_steal_pointer (&stream->pending_frame); - g_mutex_unlock (&stream->frame_mutex); - - if (!frame) - return 0; - - if (frame->rfb_cursor) - grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor); - - if (frame->cursor_moved) - { - grd_session_vnc_move_cursor (stream->session, - frame->cursor_x, - frame->cursor_y); - } - - if (frame->data) - grd_session_vnc_take_buffer (stream->session, frame->data); -+ else -+ grd_session_vnc_flush (stream->session); - - g_free (frame); - - return 0; - } - - static GrdVncFrame * - process_buffer (GrdVncPipeWireStream *stream, - struct spa_buffer *buffer) - { - size_t size; - uint8_t *map; - void *src_data; - struct spa_meta_cursor *spa_meta_cursor; - g_autofree GrdVncFrame *frame = NULL; - - frame = g_new0 (GrdVncFrame, 1); - - if (buffer->datas[0].chunk->size == 0) - { - map = NULL; - src_data = NULL; - } - else if (buffer->datas[0].type == SPA_DATA_MemFd) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) --- -2.26.2 - diff --git a/0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch b/0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch deleted file mode 100644 index 25e5f46..0000000 --- a/0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 9ad54e84aaa5f5ddae5cb16a2726b314d6229076 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 27 Aug 2020 14:04:03 -0400 -Subject: [PATCH 5/6] vnc-pipewire-stream: Correct memcpy size calculation - -commit 78c5bcb181fe2b0b9fc17eea696feac8b504df54 introduced code -to try to account for a row stride mismatch between source and -destination. - -That commit, however, erroneously copies destination stride bytes -from the source, which will lead to out of bounds access if the -source has a smaller row stride. - -This commit addresses the problem, by instead, copying just the -pixel data, and none of the row margin. - -https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/merge_requests/18 ---- - src/grd-vnc-pipewire-stream.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index ec23b0a..b94e761 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -330,73 +330,75 @@ process_buffer (GrdVncPipeWireStream *stream, - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) - { - int fd; - - fd = buffer->datas[0].fd; - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - sync_dma_buf (fd, DMA_BUF_SYNC_START); - - src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); - } - else if (buffer->datas[0].type == SPA_DATA_MemPtr) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = NULL; - src_data = buffer->datas[0].data; - } - else - { - return NULL; - } - - if (src_data) - { - int src_stride; - int dst_stride; -+ int width; - int height; - int y; - - src_stride = buffer->datas[0].chunk->stride; - dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session); - height = stream->spa_format.size.height; -+ width = stream->spa_format.size.width; - - frame->data = g_malloc (height * dst_stride); - for (y = 0; y < height; y++) - { - memcpy (((uint8_t *) frame->data) + y * dst_stride, - ((uint8_t *) src_data) + y * src_stride, -- dst_stride); -+ width * 4); - } - } - - if (map) - { - if (buffer->datas[0].type == SPA_DATA_DmaBuf) - sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END); - munmap (map, size); - } - - spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor, - sizeof *spa_meta_cursor); - if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor)) - { - struct spa_meta_bitmap *spa_meta_bitmap; - GrdPixelFormat format; - - if (spa_meta_cursor->bitmap_offset) - { - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - } - else - { - spa_meta_bitmap = NULL; - } - - if (spa_meta_bitmap && - spa_meta_bitmap->size.width > 0 && --- -2.26.2 - diff --git a/0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch b/0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch deleted file mode 100644 index 80890a0..0000000 --- a/0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch +++ /dev/null @@ -1,116 +0,0 @@ -From e8181aa61ca8e72ea607390b4368639d71d65700 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 28 Aug 2020 12:34:45 -0400 -Subject: [PATCH 6/6] vnc-pipewire-stream: Handle mmap failure better - -Right now if mmap fails, we just sort of crash. - -This commit changes the code to warn why it failed, and then -continue marching along. ---- - src/grd-vnc-pipewire-stream.c | 25 ++++++++++++++++++++++--- - 1 file changed, 22 insertions(+), 3 deletions(-) - -diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c -index b94e761..1feaef1 100644 ---- a/src/grd-vnc-pipewire-stream.c -+++ b/src/grd-vnc-pipewire-stream.c -@@ -301,73 +301,92 @@ do_render (struct spa_loop *loop, - grd_session_vnc_take_buffer (stream->session, frame->data); - else - grd_session_vnc_flush (stream->session); - - g_free (frame); - - return 0; - } - - static GrdVncFrame * - process_buffer (GrdVncPipeWireStream *stream, - struct spa_buffer *buffer) - { - size_t size; - uint8_t *map; - void *src_data; - struct spa_meta_cursor *spa_meta_cursor; - g_autofree GrdVncFrame *frame = NULL; - - frame = g_new0 (GrdVncFrame, 1); - - if (buffer->datas[0].chunk->size == 0) - { - map = NULL; - src_data = NULL; - } - else if (buffer->datas[0].type == SPA_DATA_MemFd) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); -- src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); -+ -+ if (map != MAP_FAILED) -+ { -+ src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); -+ } -+ else -+ { -+ g_warning ("Could not map memfd: %m"); -+ map = NULL; -+ src_data = NULL; -+ } - } - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) - { - int fd; - - fd = buffer->datas[0].fd; - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); -- sync_dma_buf (fd, DMA_BUF_SYNC_START); - -- src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); -+ if (map != MAP_FAILED) -+ { -+ sync_dma_buf (fd, DMA_BUF_SYNC_START); -+ src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t); -+ } -+ else -+ { -+ g_warning ("Could not map dma-buf: %m"); -+ map = NULL; -+ src_data = NULL; -+ } - } - else if (buffer->datas[0].type == SPA_DATA_MemPtr) - { - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - map = NULL; - src_data = buffer->datas[0].data; - } - else - { - return NULL; - } - - if (src_data) - { - int src_stride; - int dst_stride; - int width; - int height; - int y; - - src_stride = buffer->datas[0].chunk->stride; - dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session); - height = stream->spa_format.size.height; - width = stream->spa_format.size.width; - - frame->data = g_malloc (height * dst_stride); - for (y = 0; y < height; y++) - { - memcpy (((uint8_t *) frame->data) + y * dst_stride, - ((uint8_t *) src_data) + y * src_stride, --- -2.26.2 - diff --git a/gnome-remote-desktop.spec b/gnome-remote-desktop.spec index 81033a3..5d15c82 100644 --- a/gnome-remote-desktop.spec +++ b/gnome-remote-desktop.spec @@ -1,41 +1,72 @@ -%global systemd_unit gnome-remote-desktop.service +%global systemd_unit_handover gnome-remote-desktop-handover.service +%global systemd_unit_headless gnome-remote-desktop-headless.service +%global systemd_unit_system gnome-remote-desktop.service +%global systemd_unit_user gnome-remote-desktop.service + +%global tarball_version %%(echo %{version} | tr '~' '.') + +%bcond rdp %[0%{?fedora} || 0%{?rhel} >= 10] +%bcond vnc %[0%{?fedora} || 0%{?rhel} < 10] + +%global libei_version 1.0.901 +%global pipewire_version 0.3.49 Name: gnome-remote-desktop -Version: 0.1.8 -Release: 5%{?dist} +Version: 49.2 +Release: %autorelease Summary: GNOME Remote Desktop screen share service -License: GPLv2+ -URL: https://gitlab.gnome.org/jadahl/gnome-remote-desktop -Source0: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/uploads/20e4965351cdbd8dc32ff9801e884b91/gnome-remote-desktop-0.1.8.tar.xz +License: GPL-2.0-or-later +URL: https://gitlab.gnome.org/GNOME/gnome-remote-desktop +Source0: https://download.gnome.org/sources/%{name}/49/%{name}-%{tarball_version}.tar.xz # Adds encryption support (requires patched LibVNCServer) -Patch0: anon-tls-support.patch +Patch0: gnutls-anontls.patch -Patch10001: 0001-vnc-pipewire-stream-Handle-stride-mismatch.patch -Patch10002: 0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch -Patch10003: 0003-session-vnc-Add-API-to-flush.patch -Patch10004: 0004-vnc-pipewire-stream-Flush-connection-if-no-new-pixel.patch -Patch10005: 0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch -Patch10006: 0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch -Patch10007: 0001-vnc-Drop-frames-if-client-is-gone.patch - -BuildRequires: git +BuildRequires: asciidoc BuildRequires: gcc -BuildRequires: meson >= 0.36.0 -BuildRequires: pkgconfig -BuildRequires: pkgconfig(glib-2.0) >= 2.32 -BuildRequires: pkgconfig(gio-unix-2.0) >= 2.32 -BuildRequires: pkgconfig(libpipewire-0.3) >= 0.3.0 -BuildRequires: pkgconfig(libvncserver) >= 0.9.11-7 -BuildRequires: pkgconfig(libsecret-1) -BuildRequires: pkgconfig(libnotify) +BuildRequires: meson >= 0.47.0 +BuildRequires: systemd-rpm-macros +BuildRequires: pkgconfig(cairo) +BuildRequires: pkgconfig(epoxy) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(ffnvcodec) +%if %{with rdp} +BuildRequires: glslc +BuildRequires: spirv-tools +BuildRequires: pkgconfig(fdk-aac) +BuildRequires: pkgconfig(freerdp3) +BuildRequires: pkgconfig(fuse3) +BuildRequires: pkgconfig(libva) +BuildRequires: pkgconfig(opus) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(vulkan) +BuildRequires: pkgconfig(winpr3) +%endif +BuildRequires: pkgconfig(gbm) +BuildRequires: pkgconfig(glib-2.0) >= 2.68 +BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(gnutls) +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(libei-1.0) >= %{libei_version} +BuildRequires: pkgconfig(libnotify) +BuildRequires: pkgconfig(libpipewire-0.3) +BuildRequires: pkgconfig(libsecret-1) +%if %{with vnc} +BuildRequires: pkgconfig(libvncserver) >= 0.9.11-7 +%endif +BuildRequires: pkgconfig(systemd) +BuildRequires: pkgconfig(xkbcommon) +BuildRequires: pkgconfig(tss2-esys) +BuildRequires: pkgconfig(tss2-mu) +BuildRequires: pkgconfig(tss2-rc) +BuildRequires: pkgconfig(tss2-tctildr) -%{?systemd_requires} -BuildRequires: systemd +Requires: libei%{?_isa} >= %{libei_version} +Requires: pipewire%{?_isa} >= %{pipewire_version} -Requires: pipewire >= 0.3.0 +Obsoletes: vino < 3.22.0-21 %description GNOME Remote Desktop is a remote desktop and screen sharing service for the @@ -43,102 +74,81 @@ GNOME desktop environment. %prep -%autosetup -S git +%autosetup -p1 -n %{name}-%{tarball_version} %build -%meson +%meson \ +%if %{with rdp} + -Drdp=true \ +%else + -Drdp=false \ +%endif +%if %{with vnc} + -Dvnc=true \ +%else + -Dvnc=false \ +%endif + -Dsystemd=true \ + -Dtests=false %meson_build %install %meson_install +%find_lang %{name} + %post -%systemd_user_post %{systemd_unit} +%systemd_post %{systemd_unit_system} +%systemd_user_post %{systemd_unit_handover} +%systemd_user_post %{systemd_unit_headless} +%systemd_user_post %{systemd_unit_user} %preun -%systemd_user_preun %{systemd_unit} +%systemd_preun %{systemd_unit_system} +%systemd_user_preun %{systemd_unit_handover} +%systemd_user_preun %{systemd_unit_headless} +%systemd_user_preun %{systemd_unit_user} %postun -%systemd_user_postun_with_restart %{systemd_unit} +%systemd_postun_with_restart %{systemd_unit_system} +%systemd_user_postun_with_restart %{systemd_unit_handover} +%systemd_user_postun_with_restart %{systemd_unit_headless} +%systemd_user_postun_with_restart %{systemd_unit_user} -%files +%files -f %{name}.lang %license COPYING -%doc README +%doc README.md +%{_bindir}/grdctl %{_libexecdir}/gnome-remote-desktop-daemon -%{_userunitdir}/gnome-remote-desktop.service +%{_libexecdir}/gnome-remote-desktop-enable-service +%{_libexecdir}/gnome-remote-desktop-configuration-daemon +%{_userunitdir}/%{systemd_unit_user} +%{_userunitdir}/%{systemd_unit_headless} +%{_userunitdir}/%{systemd_unit_handover} +%{_unitdir}/%{systemd_unit_system} +%{_unitdir}/gnome-remote-desktop-configuration.service +%{_datadir}/applications/org.gnome.RemoteDesktop.Handover.desktop +%{_datadir}/dbus-1/system-services/org.gnome.RemoteDesktop.Configuration.service +%{_datadir}/dbus-1/system.d/org.gnome.RemoteDesktop.conf %{_datadir}/glib-2.0/schemas/org.gnome.desktop.remote-desktop.gschema.xml %{_datadir}/glib-2.0/schemas/org.gnome.desktop.remote-desktop.enums.xml +%{_datadir}/polkit-1/actions/org.gnome.remotedesktop.configure-system-daemon.policy +%{_datadir}/polkit-1/actions/org.gnome.remotedesktop.enable-system-daemon.policy +%{_datadir}/polkit-1/rules.d/20-gnome-remote-desktop.rules +%{_sysusersdir}/gnome-remote-desktop-sysusers.conf +%{_tmpfilesdir}/gnome-remote-desktop-tmpfiles.conf + +%if %{with rdp} +%{_datadir}/gnome-remote-desktop/ +%endif +%{_mandir}/man1/grdctl.1* %changelog -* Wed Sep 16 2020 Jonas Ådahl - 0.1.8-5 -- Fix crash when reconnecting - -* Thu Aug 27 2020 Ray Strode - 0.1.8-4 -- Fix other crash - Related: #1844993 - -* Thu Aug 27 2020 Ray Strode - 0.1.8-3 -- Fix crash - Related: #1844993 - -* Mon Jun 1 2020 Felipe Borges - 0.1.8-2 -- Fix black screen issue in remote connections on Wayland - -* Wed Mar 11 2020 Jonas Ådahl - 0.1.8-1 -- Update to 0.1.8 - -* Tue Jan 28 2020 Fedora Release Engineering - 0.1.7-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Thu Jul 25 2019 Fedora Release Engineering - 0.1.7-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Mon Mar 4 2019 Jonas Ådahl - 0.1.7-1 -- Update to 0.1.7 - -* Thu Jan 31 2019 Fedora Release Engineering - 0.1.6-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Tue Oct 2 2018 Jonas Ådahl - 0.1.6-2 -- Don't crash when PipeWire disconnects (rhbz#1632781) - -* Tue Aug 7 2018 Jonas Ådahl - 0.1.6 -- Update to 0.1.6 -- Apply ANON-TLS patch -- Depend on pipewire 0.2.2 - -* Fri Jul 13 2018 Fedora Release Engineering - 0.1.4-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Wed May 30 2018 Jonas Ådahl - 0.1.4-1 -- Update to new version - -* Fri Feb 09 2018 Igor Gnatenko - 0.1.2-5 -- Escape macros in %%changelog - -* Wed Feb 07 2018 Fedora Release Engineering - 0.1.2-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Tue Aug 29 2017 Jonas Ådahl - 0.1.2-3 -- Use %%autosetup -- Install licence file - -* Tue Aug 22 2017 Jonas Ådahl - 0.1.2-2 -- Remove gschema compilation step as that had been deprecated - -* Mon Aug 21 2017 Jonas Ådahl - 0.1.2-1 -- Update to 0.1.2 -- Changed tabs to spaces -- Added systemd user macros -- Install to correct systemd user unit directory -- Compile gsettings schemas after install and uninstall - -* Mon Aug 21 2017 Jonas Ådahl - 0.1.1-1 -- First packaged version +%autochangelog diff --git a/anon-tls-support.patch b/gnutls-anontls.patch similarity index 77% rename from anon-tls-support.patch rename to gnutls-anontls.patch index b0bd073..6151d72 100644 --- a/anon-tls-support.patch +++ b/gnutls-anontls.patch @@ -1,7 +1,7 @@ -From f431e71d2a40db2fcfc8f88ba5899b4b938b4c2f Mon Sep 17 00:00:00 2001 +From 005617f3e2cb59241dc02c2db714c2b934553acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 14 Jun 2018 12:21:37 +0200 -Subject: [PATCH 1/6] vnc: Add anonymous TLS encryption support +Subject: [PATCH 1/7] vnc: Add anonymous TLS encryption support Add support for encrypting the VNC connection using anonymous TLS. In effect this means that the channel is encrypted using TLS but that no @@ -11,36 +11,36 @@ VNC connection. --- meson.build | 1 + src/grd-enums.h | 6 + - src/grd-session-vnc.c | 98 +++- - src/grd-session-vnc.h | 15 + - src/grd-settings.c | 28 ++ - src/grd-settings.h | 2 + - src/grd-vnc-server.c | 45 ++ + src/grd-session-vnc.c | 120 ++++- + src/grd-session-vnc.h | 17 + + src/grd-settings-user.c | 4 + + src/grd-settings.c | 18 + + src/grd-vnc-server.c | 49 ++ src/grd-vnc-tls.c | 444 ++++++++++++++++++ src/grd-vnc-tls.h | 28 ++ - src/meson.build | 5 +- + src/meson.build | 3 + ...nome.desktop.remote-desktop.gschema.xml.in | 10 + - 11 files changed, 666 insertions(+), 16 deletions(-) + 11 files changed, 674 insertions(+), 26 deletions(-) create mode 100644 src/grd-vnc-tls.c create mode 100644 src/grd-vnc-tls.h diff --git a/meson.build b/meson.build -index 516656e..db77711 100644 +index 5dcb77c3..269238c0 100644 --- a/meson.build +++ b/meson.build -@@ -15,6 +15,7 @@ libvncserver_dep = dependency('libvncserver') - libvncclient_dep = dependency('libvncclient') - libsecret_dep = dependency('libsecret-1') - libnotify_dep = dependency('libnotify') -+gnutls_dep = dependency('gnutls') +@@ -70,6 +70,7 @@ endif + if have_vnc + libvncclient_dep = dependency('libvncclient') + libvncserver_dep = dependency('libvncserver') ++ gnutls_dep = dependency('gnutls') + endif - cdata = configuration_data() - cdata.set_quoted('GETTEXT_PACKAGE', 'gnome-remote-desktop') + prefix = get_option('prefix') diff --git a/src/grd-enums.h b/src/grd-enums.h -index ffab821..4333863 100644 +index 25b42661..f4438764 100644 --- a/src/grd-enums.h +++ b/src/grd-enums.h -@@ -27,4 +27,10 @@ typedef enum +@@ -32,6 +32,12 @@ typedef enum GRD_VNC_AUTH_METHOD_PASSWORD } GrdVncAuthMethod; @@ -50,12 +50,14 @@ index ffab821..4333863 100644 + GRD_VNC_ENCRYPTION_TLS_ANON = 1 << 1, +} GrdVncEncryption; + - #endif /* GRD_ENUMS_H */ + typedef enum + { + GRD_VNC_SCREEN_SHARE_MODE_MIRROR_PRIMARY, diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index 4cdc379..6d489cc 100644 +index f7e14080..b5e4fe13 100644 --- a/src/grd-session-vnc.c +++ b/src/grd-session-vnc.c -@@ -44,7 +44,9 @@ struct _GrdSessionVnc +@@ -46,7 +46,9 @@ struct _GrdSessionVnc { GrdSession parent; @@ -65,7 +67,7 @@ index 4cdc379..6d489cc 100644 GSource *source; rfbScreenInfoPtr rfb_screen; rfbClientPtr rfb_client; -@@ -508,12 +510,30 @@ check_rfb_password (rfbClientPtr rfb_client, +@@ -608,6 +610,12 @@ check_rfb_password (rfbClientPtr rfb_client, } } @@ -76,9 +78,10 @@ index 4cdc379..6d489cc 100644 +} + int - grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc) - { - return session_vnc->rfb_screen->paddedWidthInBytes; + grd_session_vnc_get_stride_for_width (GrdSessionVnc *session_vnc, + int width) +@@ -615,6 +623,18 @@ grd_session_vnc_get_stride_for_width (GrdSessionVnc *session_vnc, + return width * BGRX_BYTES_PER_PIXEL; } +rfbClientPtr @@ -96,7 +99,7 @@ index 4cdc379..6d489cc 100644 static void init_vnc_session (GrdSessionVnc *session_vnc) { -@@ -554,33 +574,74 @@ init_vnc_session (GrdSessionVnc *session_vnc) +@@ -689,44 +709,85 @@ init_vnc_session (GrdSessionVnc *session_vnc) rfbProcessEvents (rfb_screen, 0); } @@ -131,6 +134,17 @@ index 4cdc379..6d489cc 100644 + session_vnc->pending_framebuffer_width, + session_vnc->pending_framebuffer_height); + session_vnc->pending_framebuffer_resize = FALSE; ++ ++ /** ++ * This is a workaround. libvncserver is unable to handle clipboard ++ * changes early and either disconnects the client or crashes g-r-d ++ * if it receives rfbSendServerCutText too early altough the ++ * authentification process is already done. ++ * Doing this after resizing the framebuffer, seems to work fine, ++ * so enable the clipboard here and not when the remote desktop ++ * session proxy is acquired. ++ */ ++ grd_clipboard_vnc_maybe_enable_clipboard (session_vnc->clipboard_vnc); + } + } + @@ -172,6 +186,17 @@ index 4cdc379..6d489cc 100644 - session_vnc->pending_framebuffer_width, - session_vnc->pending_framebuffer_height); - session_vnc->pending_framebuffer_resize = FALSE; +- +- /** +- * This is a workaround. libvncserver is unable to handle clipboard +- * changes early and either disconnects the client or crashes g-r-d +- * if it receives rfbSendServerCutText too early altough the +- * authentification process is already done. +- * Doing this after resizing the framebuffer, seems to work fine, +- * so enable the clipboard here and not when the remote desktop +- * session proxy is acquired. +- */ +- grd_clipboard_vnc_maybe_enable_clipboard (session_vnc->clipboard_vnc); - } + grd_session_stop (session); } @@ -185,7 +210,7 @@ index 4cdc379..6d489cc 100644 } return G_SOURCE_CONTINUE; -@@ -593,7 +654,10 @@ grd_session_vnc_attach_source (GrdSessionVnc *session_vnc) +@@ -739,7 +800,10 @@ grd_session_vnc_attach_source (GrdSessionVnc *session_vnc) socket = g_socket_connection_get_socket (session_vnc->connection); session_vnc->source = g_socket_create_source (socket, @@ -197,18 +222,23 @@ index 4cdc379..6d489cc 100644 NULL); g_source_set_callback (session_vnc->source, (GSourceFunc) handle_socket_data, -@@ -619,8 +683,10 @@ grd_session_vnc_new (GrdVncServer *vnc_server, +@@ -780,6 +844,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server, "context", context, NULL); + session_vnc->vnc_server = vnc_server; session_vnc->connection = g_object_ref (connection); + settings = grd_context_get_settings (context); +@@ -792,6 +857,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server, + G_CALLBACK (on_view_only_changed), + session_vnc); + + grd_session_vnc_grab_socket (session_vnc, vnc_socket_grab_func); grd_session_vnc_attach_source (session_vnc); init_vnc_session (session_vnc); -@@ -635,6 +701,8 @@ grd_session_vnc_dispose (GObject *object) +@@ -806,6 +872,8 @@ grd_session_vnc_dispose (GObject *object) g_assert (!session_vnc->rfb_screen); @@ -218,12 +248,12 @@ index 4cdc379..6d489cc 100644 G_OBJECT_CLASS (grd_session_vnc_parent_class)->dispose (object); diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h -index 25919b6..e0601c3 100644 +index 8fc71850..3c08f812 100644 --- a/src/grd-session-vnc.h +++ b/src/grd-session-vnc.h @@ -36,6 +36,9 @@ G_DECLARE_FINAL_TYPE (GrdSessionVnc, GRD, SESSION_VNC, - GrdSession); + GrdSession) +typedef gboolean (* GrdVncSocketGrabFunc) (GrdSessionVnc *session_vnc, + GError **error); @@ -231,14 +261,16 @@ index 25919b6..e0601c3 100644 GrdSessionVnc *grd_session_vnc_new (GrdVncServer *vnc_server, GSocketConnection *connection); -@@ -53,6 +56,18 @@ void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc, - int x, - int y); +@@ -62,4 +65,18 @@ void grd_session_vnc_set_client_clipboard_text (GrdSessionVnc *session_vnc, + int grd_session_vnc_get_stride_for_width (GrdSessionVnc *session_vnc, + int width); +int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc); + - int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc); - ++int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc); ++ + gboolean grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc); ++ +rfbClientPtr grd_session_vnc_get_rfb_client (GrdSessionVnc *session_vnc); + +void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, @@ -248,96 +280,81 @@ index 25919b6..e0601c3 100644 + GrdVncSocketGrabFunc grab_func); + +GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc); +diff --git a/src/grd-settings-user.c b/src/grd-settings-user.c +index 1bd679e4..c54e0b80 100644 +--- a/src/grd-settings-user.c ++++ b/src/grd-settings-user.c +@@ -91,6 +91,10 @@ grd_settings_user_constructed (GObject *object) + g_settings_bind (settings->vnc_settings, "screen-share-mode", + settings, "vnc-screen-share-mode", + G_SETTINGS_BIND_DEFAULT); ++ g_settings_bind (settings->vnc_settings, "encryption", ++ settings, "vnc-encryption", ++ G_SETTINGS_BIND_DEFAULT); + - #endif /* GRD_SESSION_VNC_H */ + + G_OBJECT_CLASS (grd_settings_user_parent_class)->constructed (object); + } diff --git a/src/grd-settings.c b/src/grd-settings.c -index bdf8211..7324310 100644 +index 8393ace5..a65385ef 100644 --- a/src/grd-settings.c +++ b/src/grd-settings.c -@@ -48,6 +48,7 @@ struct _GrdSettings - gboolean view_only; - GrdVncAuthMethod auth_method; - int port; -+ GrdVncEncryption encryption; - } vnc; +@@ -58,6 +58,7 @@ enum + PROP_RDP_SERVER_CERT_PATH, + PROP_RDP_SERVER_KEY_PATH, + PROP_VNC_AUTH_METHOD, ++ PROP_VNC_ENCRYPTION, }; -@@ -120,6 +121,12 @@ grd_settings_get_vnc_auth_method (GrdSettings *settings) - return settings->vnc.auth_method; - } + typedef struct _GrdSettingsPrivate +@@ -84,6 +85,7 @@ typedef struct _GrdSettingsPrivate + gboolean view_only; + GrdVncScreenShareMode screen_share_mode; + GrdVncAuthMethod auth_method; ++ GrdVncEncryption encryption; + } vnc; + } GrdSettingsPrivate; -+GrdVncEncryption -+grd_settings_get_vnc_encryption (GrdSettings *settings) -+{ -+ return settings->vnc.encryption; -+} -+ - static void - update_vnc_view_only (GrdSettings *settings) - { -@@ -134,6 +141,13 @@ update_vnc_auth_method (GrdSettings *settings) - "auth-method"); - } - -+static void -+update_vnc_encryption (GrdSettings *settings) -+{ -+ settings->vnc.encryption = g_settings_get_flags (settings->vnc.settings, -+ "encryption"); -+} -+ - static void - on_vnc_settings_changed (GSettings *vnc_settings, - const char *key, -@@ -149,6 +163,11 @@ on_vnc_settings_changed (GSettings *vnc_settings, - update_vnc_auth_method (settings); - g_signal_emit (settings, signals[VNC_AUTH_METHOD_CHANGED], 0); +@@ -426,6 +428,9 @@ grd_settings_get_property (GObject *object, + else + g_value_set_enum (value, priv->vnc.auth_method); + break; ++ case PROP_VNC_ENCRYPTION: ++ g_value_set_flags (value, priv->vnc.encryption); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } -+ else if (strcmp (key, "encryption") == 0) -+ { -+ update_vnc_encryption (settings); -+ g_signal_emit (settings, signals[VNC_ENCRYPTION_CHANGED], 0); -+ } +@@ -563,6 +568,9 @@ grd_settings_set_property (GObject *object, + case PROP_VNC_AUTH_METHOD: + priv->vnc.auth_method = g_value_get_enum (value); + break; ++ case PROP_VNC_ENCRYPTION: ++ priv->vnc.encryption = g_value_get_flags (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +@@ -744,4 +752,14 @@ grd_settings_class_init (GrdSettingsClass *klass) + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property (object_class, ++ PROP_VNC_ENCRYPTION, ++ g_param_spec_flags ("vnc-encryption", ++ "vnc encryption", ++ "vnc encryption", ++ GRD_TYPE_VNC_ENCRYPTION, ++ GRD_VNC_ENCRYPTION_TLS_ANON, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT | ++ G_PARAM_STATIC_STRINGS)); } - - static void -@@ -172,6 +191,8 @@ grd_settings_init (GrdSettings *settings) - update_vnc_auth_method (settings); - - settings->vnc.port = GRD_VNC_SERVER_PORT; -+ -+ update_vnc_encryption (settings); - } - - static void -@@ -195,4 +216,11 @@ grd_settings_class_init (GrdSettingsClass *klass) - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -+ signals[VNC_ENCRYPTION_CHANGED] = -+ g_signal_new ("vnc-encryption-changed", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ 0, -+ NULL, NULL, NULL, -+ G_TYPE_NONE, 0); - } -diff --git a/src/grd-settings.h b/src/grd-settings.h -index e4e0c09..0575ec1 100644 ---- a/src/grd-settings.h -+++ b/src/grd-settings.h -@@ -45,4 +45,6 @@ gboolean grd_settings_get_vnc_view_only (GrdSettings *settings); - - GrdVncAuthMethod grd_settings_get_vnc_auth_method (GrdSettings *settings); - -+GrdVncEncryption grd_settings_get_vnc_encryption (GrdSettings *settings); -+ - #endif /* GRD_SETTINGS_H */ diff --git a/src/grd-vnc-server.c b/src/grd-vnc-server.c -index a6d95cb..f9c68db 100644 +index 83220655..2f8229b2 100644 --- a/src/grd-vnc-server.c +++ b/src/grd-vnc-server.c -@@ -24,11 +24,13 @@ +@@ -24,6 +24,7 @@ #include "grd-vnc-server.h" @@ -345,13 +362,15 @@ index a6d95cb..f9c68db 100644 #include #include - #include "grd-context.h" +@@ -31,6 +32,7 @@ + #include "grd-debug.h" #include "grd-session-vnc.h" + #include "grd-utils.h" +#include "grd-vnc-tls.h" - enum -@@ -130,6 +132,43 @@ on_incoming (GSocketService *service, + { +@@ -130,6 +132,45 @@ on_incoming (GSocketService *service, return TRUE; } @@ -363,7 +382,9 @@ index a6d95cb..f9c68db 100644 + GrdVncEncryption encryption; + + tls_security_handler = grd_vnc_tls_get_security_handler (); -+ encryption = grd_settings_get_vnc_encryption (settings); ++ g_object_get (G_OBJECT (settings), ++ "vnc-encryption", &encryption, ++ NULL); + + if (encryption == (GRD_VNC_ENCRYPTION_NONE | GRD_VNC_ENCRYPTION_TLS_ANON)) + { @@ -395,18 +416,19 @@ index a6d95cb..f9c68db 100644 gboolean grd_vnc_server_start (GrdVncServer *vnc_server, GError **error) -@@ -220,12 +259,18 @@ static void +@@ -242,11 +283,19 @@ grd_vnc_server_dispose (GObject *object) + static void grd_vnc_server_constructed (GObject *object) { - GrdVncServer *vnc_server = GRD_VNC_SERVER (object); ++ GrdVncServer *vnc_server = GRD_VNC_SERVER (object); + GrdSettings *settings = grd_context_get_settings (vnc_server->context); - - if (grd_context_get_debug_flags (vnc_server->context) & GRD_DEBUG_VNC) ++ + if (grd_get_debug_flags () & GRD_DEBUG_VNC) rfbLogEnable (1); else rfbLogEnable (0); -+ g_signal_connect (settings, "vnc-encryption-changed", ++ g_signal_connect (settings, "notify::vnc-encryption", + G_CALLBACK (on_vnc_encryption_changed), + vnc_server); + sync_encryption_settings (vnc_server); @@ -416,7 +438,7 @@ index a6d95cb..f9c68db 100644 diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c new file mode 100644 -index 0000000..ec4758e +index 00000000..ec4758e0 --- /dev/null +++ b/src/grd-vnc-tls.c @@ -0,0 +1,444 @@ @@ -866,7 +888,7 @@ index 0000000..ec4758e +} diff --git a/src/grd-vnc-tls.h b/src/grd-vnc-tls.h new file mode 100644 -index 0000000..135ef8c +index 00000000..135ef8c7 --- /dev/null +++ b/src/grd-vnc-tls.h @@ -0,0 +1,28 @@ @@ -899,34 +921,29 @@ index 0000000..135ef8c + +#endif /* GRD_VNC_TLS_H */ diff --git a/src/meson.build b/src/meson.build -index 0f76fab..9d2f1ce 100644 +index 1b2cb93d..6b8b517e 100644 --- a/src/meson.build +++ b/src/meson.build -@@ -21,6 +21,8 @@ daemon_sources = files([ - 'grd-vnc-pipewire-stream.h', - 'grd-vnc-server.c', - 'grd-vnc-server.h', -+ 'grd-vnc-tls.c', -+ 'grd-vnc-tls.h', - ]) +@@ -274,10 +274,13 @@ if have_vnc + 'grd-vnc-pipewire-stream.h', + 'grd-vnc-server.c', + 'grd-vnc-server.h', ++ 'grd-vnc-tls.c', ++ 'grd-vnc-tls.h', + ]) + + deps += [ + libvncserver_dep, ++ gnutls_dep, + ] + endif - gen_daemon_sources = [] -@@ -51,7 +53,8 @@ executable('gnome-remote-desktop-daemon', - pipewire_dep, - libvncserver_dep, - libsecret_dep, -- libnotify_dep], -+ libnotify_dep, -+ gnutls_dep], - include_directories: [configinc], - install: true, - install_dir: libexecdir) diff --git a/src/org.gnome.desktop.remote-desktop.gschema.xml.in b/src/org.gnome.desktop.remote-desktop.gschema.xml.in -index a5c2022..846e65b 100644 +index 2986a0e5..a0169789 100644 --- a/src/org.gnome.desktop.remote-desktop.gschema.xml.in +++ b/src/org.gnome.desktop.remote-desktop.gschema.xml.in -@@ -23,5 +23,15 @@ - * password - by requiring the remote client to provide a known password +@@ -173,6 +173,16 @@ + configuration updates. + @@ -940,15 +957,16 @@ index a5c2022..846e65b 100644 + + - + + -- -2.25.1 +2.51.0 -From 73c96bb84856362e2446645533bfff8af2e90529 Mon Sep 17 00:00:00 2001 +From bc65e13fb3687b2f79433c880525333810d6ba31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 27 Nov 2019 11:02:09 +0100 -Subject: [PATCH 2/6] session-vnc: Add paused/resumed signals +Subject: [PATCH 2/7] session-vnc: Add paused/resumed signals Paused is when the socket sourec is detached, and resumed when attached. Meant to be used by the TLS channel security to a attach/detach @@ -958,10 +976,10 @@ out-of-socket source. 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index 6d489cc..afe5889 100644 +index b5e4fe13..79de30d4 100644 --- a/src/grd-session-vnc.c +++ b/src/grd-session-vnc.c -@@ -40,14 +40,27 @@ +@@ -42,14 +42,27 @@ #define BGRX_SAMPLES_PER_PIXEL 3 #define BGRX_BYTES_PER_PIXEL 4 @@ -989,8 +1007,8 @@ index 6d489cc..afe5889 100644 rfbScreenInfoPtr rfb_screen; rfbClientPtr rfb_client; -@@ -73,7 +86,7 @@ struct _GrdSessionVnc - G_DEFINE_TYPE (GrdSessionVnc, grd_session_vnc, GRD_TYPE_SESSION); +@@ -81,7 +94,7 @@ struct _GrdSessionVnc + G_DEFINE_TYPE (GrdSessionVnc, grd_session_vnc, GRD_TYPE_SESSION) static void -grd_session_vnc_detach_source (GrdSessionVnc *session_vnc); @@ -998,7 +1016,7 @@ index 6d489cc..afe5889 100644 static gboolean close_session_idle (gpointer user_data); -@@ -215,7 +228,8 @@ handle_client_gone (rfbClientPtr rfb_client) +@@ -248,7 +261,8 @@ handle_client_gone (rfbClientPtr rfb_client) g_debug ("VNC client gone"); @@ -1006,18 +1024,18 @@ index 6d489cc..afe5889 100644 + grd_session_vnc_pause (session_vnc); + maybe_queue_close_session_idle (session_vnc); + session_vnc->rfb_client = NULL; } - -@@ -283,7 +297,7 @@ handle_new_client (rfbClientPtr rfb_client) - session_vnc->prompt_cancellable, - prompt_response_callback, - session_vnc); +@@ -338,7 +352,7 @@ handle_new_client (rfbClientPtr rfb_client) + { + case GRD_VNC_AUTH_METHOD_PROMPT: + show_sharing_desktop_prompt (session_vnc, rfb_client->host); - grd_session_vnc_detach_source (session_vnc); + grd_session_vnc_pause (session_vnc); return RFB_CLIENT_ON_HOLD; case GRD_VNC_AUTH_METHOD_PASSWORD: session_vnc->rfb_screen->passwordCheck = check_rfb_password; -@@ -501,7 +515,7 @@ check_rfb_password (rfbClientPtr rfb_client, +@@ -601,7 +615,7 @@ check_rfb_password (rfbClientPtr rfb_client, if (memcmp (challenge_encrypted, response_encrypted, len) == 0) { grd_session_start (GRD_SESSION (session_vnc)); @@ -1026,8 +1044,8 @@ index 6d489cc..afe5889 100644 return TRUE; } else -@@ -671,6 +685,36 @@ grd_session_vnc_detach_source (GrdSessionVnc *session_vnc) - g_clear_pointer (&session_vnc->source, g_source_destroy); +@@ -821,6 +835,36 @@ grd_session_vnc_detach_source (GrdSessionVnc *session_vnc) + g_clear_pointer (&session_vnc->source, g_source_unref); } +gboolean @@ -1060,10 +1078,10 @@ index 6d489cc..afe5889 100644 + g_signal_emit (session_vnc, signals[RESUMED], 0); +} + - GrdSessionVnc * - grd_session_vnc_new (GrdVncServer *vnc_server, - GSocketConnection *connection) -@@ -688,6 +732,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server, + static void + on_view_only_changed (GrdSettings *settings, + GParamSpec *pspec, +@@ -859,6 +903,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server, grd_session_vnc_grab_socket (session_vnc, vnc_socket_grab_func); grd_session_vnc_attach_source (session_vnc); @@ -1071,17 +1089,17 @@ index 6d489cc..afe5889 100644 init_vnc_session (session_vnc); -@@ -717,7 +762,7 @@ grd_session_vnc_stop (GrdSession *session) - - g_clear_object (&session_vnc->pipewire_stream); +@@ -893,7 +938,7 @@ grd_session_vnc_stop (GrdSession *session) + g_clear_object (&session_vnc->stream); + } - grd_session_vnc_detach_source (session_vnc); + grd_session_vnc_pause (session_vnc); g_clear_object (&session_vnc->connection); - g_clear_pointer (&session_vnc->rfb_screen->frameBuffer, g_free); -@@ -773,8 +818,8 @@ grd_session_vnc_stream_ready (GrdSession *session, - G_CALLBACK (on_pipwire_stream_closed), + g_clear_object (&session_vnc->clipboard_vnc); +@@ -984,8 +1029,8 @@ on_stream_ready (GrdStream *stream, + G_CALLBACK (on_pipewire_stream_closed), session_vnc); - if (!session_vnc->source) @@ -1091,10 +1109,10 @@ index 6d489cc..afe5889 100644 } static void -@@ -793,4 +838,17 @@ grd_session_vnc_class_init (GrdSessionVncClass *klass) +@@ -1021,4 +1066,17 @@ grd_session_vnc_class_init (GrdSessionVncClass *klass) session_class->stop = grd_session_vnc_stop; - session_class->stream_ready = grd_session_vnc_stream_ready; + session_class->on_stream_created = grd_session_vnc_on_stream_created; + + signals[PAUSED] = g_signal_new ("paused", + G_TYPE_FROM_CLASS (klass), @@ -1110,13 +1128,13 @@ index 6d489cc..afe5889 100644 + G_TYPE_NONE, 0); } -- -2.25.1 +2.51.0 -From fd139827f668c3fadf61a90b47c1b01a95ba0503 Mon Sep 17 00:00:00 2001 +From aabc0245e247fbffe9ae6b8281cbf2bccc9ab882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 27 Nov 2019 11:03:46 +0100 -Subject: [PATCH 3/6] session-vnc: Add grd_session_vnc_dispatch() helper +Subject: [PATCH 3/7] session-vnc: Add grd_session_vnc_dispatch() helper To be used by the TLS channel security to dispatch when there is data available that is not visible to the socket source. @@ -1126,10 +1144,10 @@ available that is not visible to the socket source. 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index afe5889..e26f145 100644 +index 79de30d4..b48b9017 100644 --- a/src/grd-session-vnc.c +++ b/src/grd-session-vnc.c -@@ -625,6 +625,21 @@ vnc_socket_grab_func (GrdSessionVnc *session_vnc, +@@ -771,6 +771,21 @@ vnc_socket_grab_func (GrdSessionVnc *session_vnc, return TRUE; } @@ -1151,7 +1169,7 @@ index afe5889..e26f145 100644 static gboolean handle_socket_data (GSocket *socket, GIOCondition condition, -@@ -641,16 +656,7 @@ handle_socket_data (GSocket *socket, +@@ -787,16 +802,7 @@ handle_socket_data (GSocket *socket, } else if (condition & G_IO_IN) { @@ -1170,26 +1188,24 @@ index afe5889..e26f145 100644 else { diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h -index e0601c3..5caa9f4 100644 +index 3c08f812..f230887e 100644 --- a/src/grd-session-vnc.h +++ b/src/grd-session-vnc.h -@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, +@@ -79,4 +79,6 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc, GrdVncSocketGrabFunc grab_func); +void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc); + GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc); - - #endif /* GRD_SESSION_VNC_H */ -- -2.25.1 +2.51.0 -From 7bdf190a3a69cecfe8027ee499b5029cfb12f3da Mon Sep 17 00:00:00 2001 +From 2d43f0586ae24b202beda4d283b25fec3e722af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 27 Nov 2019 11:05:13 +0100 -Subject: [PATCH 4/6] vnc/tls: Add some logging +Subject: [PATCH 4/7] vnc/tls: Add some logging Uses the log utility from libvncserver as it is related to the RFB protocol rather than the session itself. @@ -1198,7 +1214,7 @@ protocol rather than the session itself. 1 file changed, 9 insertions(+) diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c -index ec4758e..ac6c35f 100644 +index ec4758e0..ac6c35f6 100644 --- a/src/grd-vnc-tls.c +++ b/src/grd-vnc-tls.c @@ -67,6 +67,7 @@ grd_vnc_tls_context_new (void) @@ -1260,13 +1276,13 @@ index ec4758e..ac6c35f 100644 { g_warning ("TLS handshake failed: %s", error->message); -- -2.25.1 +2.51.0 -From 15a28c9f383b260e9b1cef37a663bff7d2efa255 Mon Sep 17 00:00:00 2001 +From 62e04d794eaf2c0acfc16af0b0968fead4bb4df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 27 Nov 2019 11:07:40 +0100 -Subject: [PATCH 5/6] vnc/tls: Dispatch also when data is pending outside of +Subject: [PATCH 5/7] vnc/tls: Dispatch also when data is pending outside of the socket gnutls may have data available in its buffers, and we have our own peek @@ -1276,14 +1292,14 @@ epoll(). Deal with this by adding a custom source that dispatches as long as there is data to read in those buffers. --- src/grd-session-vnc.h | 2 + - src/grd-vnc-tls.c | 92 ++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 88 insertions(+), 6 deletions(-) + src/grd-vnc-tls.c | 90 ++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h -index 5caa9f4..db1c7f3 100644 +index f230887e..9dd33442 100644 --- a/src/grd-session-vnc.h +++ b/src/grd-session-vnc.h -@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, +@@ -79,6 +79,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc, void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc, GrdVncSocketGrabFunc grab_func); @@ -1293,7 +1309,7 @@ index 5caa9f4..db1c7f3 100644 GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc); diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c -index ac6c35f..8f65225 100644 +index ac6c35f6..312b6b92 100644 --- a/src/grd-vnc-tls.c +++ b/src/grd-vnc-tls.c @@ -41,6 +41,12 @@ typedef enum _GrdTlsHandshakeState @@ -1318,12 +1334,7 @@ index ac6c35f..8f65225 100644 } GrdVncTlsSession; static gboolean -@@ -296,16 +304,14 @@ grd_vnc_tls_peek_at_socket (rfbClientPtr rfb_client, - peekable_len = MIN (len, tls_session->peek_buffer_len); - memcpy (buf, tls_session->peek_buffer, peekable_len); - -+ fprintf(stderr, ":::: %s:%d %s() - peeked %d bytes, can peek %d bytes\n", __FILE__, __LINE__, __func__, -+ peekable_len, tls_session->peek_buffer_len); +@@ -299,13 +307,9 @@ grd_vnc_tls_peek_at_socket (rfbClientPtr rfb_client, return peekable_len; } @@ -1339,7 +1350,7 @@ index ac6c35f..8f65225 100644 if (tls_session->peek_buffer_len > 0) return TRUE; -@@ -315,6 +321,16 @@ grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client) +@@ -315,6 +319,16 @@ grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client) return FALSE; } @@ -1356,7 +1367,7 @@ index ac6c35f..8f65225 100644 static int grd_vnc_tls_write_to_socket (rfbClientPtr rfb_client, const char *buf, -@@ -403,6 +419,62 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc, +@@ -403,6 +417,62 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc, return TRUE; } @@ -1419,7 +1430,7 @@ index ac6c35f..8f65225 100644 static void rfb_tls_security_handler (rfbClientPtr rfb_client) { -@@ -429,6 +501,14 @@ rfb_tls_security_handler (rfbClientPtr rfb_client) +@@ -429,6 +499,14 @@ rfb_tls_security_handler (rfbClientPtr rfb_client) rfb_client->hasPendingOnSocket = grd_vnc_tls_has_pending_on_socket; rfb_client->writeToSocket = grd_vnc_tls_write_to_socket; @@ -1435,13 +1446,13 @@ index ac6c35f..8f65225 100644 } -- -2.25.1 +2.51.0 -From a85de2328db0a0d3412f13a5c9f3a0c2676b6239 Mon Sep 17 00:00:00 2001 +From 799e2b287bd055c46709d0063436b819894200e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 27 Nov 2019 16:48:00 +0100 -Subject: [PATCH 6/6] session-vnc: Set our own password handling function up +Subject: [PATCH 6/7] session-vnc: Set our own password handling function up front libvncserver decides whether to register a auth security handler @@ -1457,10 +1468,10 @@ password prompt. 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c -index e26f145..740e68c 100644 +index b48b9017..87cc7d86 100644 --- a/src/grd-session-vnc.c +++ b/src/grd-session-vnc.c -@@ -91,11 +91,6 @@ grd_session_vnc_pause (GrdSessionVnc *session_vnc); +@@ -99,11 +99,6 @@ grd_session_vnc_pause (GrdSessionVnc *session_vnc); static gboolean close_session_idle (gpointer user_data); @@ -1472,7 +1483,7 @@ index e26f145..740e68c 100644 static void swap_uint8 (uint8_t *a, uint8_t *b) -@@ -300,7 +295,6 @@ handle_new_client (rfbClientPtr rfb_client) +@@ -355,7 +350,6 @@ handle_new_client (rfbClientPtr rfb_client) grd_session_vnc_pause (session_vnc); return RFB_CLIENT_ON_HOLD; case GRD_VNC_AUTH_METHOD_PASSWORD: @@ -1480,9 +1491,9 @@ index e26f145..740e68c 100644 /* * authPasswdData needs to be non NULL in libvncserver to trigger * password authentication. -@@ -584,6 +578,8 @@ init_vnc_session (GrdSessionVnc *session_vnc) - rfb_screen->frameBuffer = g_malloc0 (screen_width * screen_height * 4); - memset (rfb_screen->frameBuffer, 0x1f, screen_width * screen_height * 4); +@@ -719,6 +713,8 @@ init_vnc_session (GrdSessionVnc *session_vnc) + session_vnc->monitor_config->connectors = connectors; + } + rfb_screen->passwordCheck = check_rfb_password; + @@ -1490,5 +1501,41 @@ index e26f145..740e68c 100644 rfbProcessEvents (rfb_screen, 0); } -- -2.25.1 +2.51.0 + + +From b74286bdb8876d27d279c725357d73a23a3316b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 12 Oct 2020 17:34:30 +0200 +Subject: [PATCH 7/7] vnc: Copy pixels using the right destination stride + +We're copying the pixels in a separate thread managed by PipeWire, and +in this thread, accessing the VNC framebuffer dimension and stride is +racy. Instead of fetching the dimension directly, pass the expected +width and get the stride it will eventually have. + +Already before this patch, when the copied pixel end up on the main +thread and the dimension still doesn't match up, the frame will be +dropped. +--- + src/grd-session-vnc.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h +index 9dd33442..98c73451 100644 +--- a/src/grd-session-vnc.h ++++ b/src/grd-session-vnc.h +@@ -67,7 +67,8 @@ int grd_session_vnc_get_stride_for_width (GrdSessionVnc *session_vnc, + + int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc); + +-int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc); ++int grd_session_vnc_get_stride_for_width (GrdSessionVnc *session_vnc, ++ int width); + + gboolean grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc); + +-- +2.51.0 + diff --git a/plans/main.fmf b/plans/main.fmf new file mode 100644 index 0000000..ae0c305 --- /dev/null +++ b/plans/main.fmf @@ -0,0 +1,6 @@ +summary: Run all tests +execute: + how: tmt +discover: + how: fmf + diff --git a/sources b/sources index 0cd4e90..d817ea5 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (gnome-remote-desktop-0.1.8.tar.xz) = 83e7d9e356c7121d6d102e2f0159f3ff20d039d705dd1ffa7c582a90aa2f433aa6f0153b972f1f2a4da928f842bfb7a950e7ba4b8ff6fda1deb8cf7792114315 +SHA512 (gnome-remote-desktop-49.2.tar.xz) = b678ee125e1b5f6d58e85f57a332cf02ee6b5dee654469e66f496f9467e6512a701a3e37a9580562e0b064320380d2df4ca6b15e20bd35b1605b4bd9de73827c diff --git a/tests/got-audit/got-audit.gdb b/tests/got-audit/got-audit.gdb new file mode 100644 index 0000000..6661297 --- /dev/null +++ b/tests/got-audit/got-audit.gdb @@ -0,0 +1,2 @@ +gef config gef.disable_color True +got-audit --all diff --git a/tests/got-audit/main.fmf b/tests/got-audit/main.fmf new file mode 100644 index 0000000..25caf1d --- /dev/null +++ b/tests/got-audit/main.fmf @@ -0,0 +1,10 @@ +summary: Audit the GOT for signs of tampering +description: | + Pointers in the server process GOT will be checked to ensure that + each function pointer's value is within a shared object file + that exports a symbol of that name, and that no shared object + files export conflicting symbols. +contact: Gordon Messmer +require+: + - gdb-gef # needed to test got-audit + - gnome-remote-desktop diff --git a/tests/got-audit/runtest.sh b/tests/got-audit/runtest.sh new file mode 100755 index 0000000..c4b9b29 --- /dev/null +++ b/tests/got-audit/runtest.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /CoreOS/gnome-remote-desktop/Sanity/got-audit +# Description: Check pointers in the server process GOT for signs of tampering +# Author: Gordon Messmer +# + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "systemctl start --user gnome-remote-desktop-headless" + rlRun "TestDir=\$(pwd)" + rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" + rlRun "pushd $TmpDir" + rlRun "auditfile=\$(mktemp --tmpdir=${TmpDir})" + rlPhaseEnd + + rlPhaseStartTest "Run GEF got-audit" + rlRun "SERVICE_PID=\$( systemctl show --property=MainPID --user gnome-remote-desktop-headless.service | cut -f2 -d= )" + rlRun "echo SERVICE_PID is '$SERVICE_PID'" + [ -n "$SERVICE_PID" ] || rlFail "No service pid was found" + rlRun "gdb-gef --pid '$SERVICE_PID' --command='$TestDir'/got-audit.gdb --batch > '$auditfile'" + # Basic test: ensure that at least one symbol is found in libc.so, + # to verify that the report looks plausible. + rlAssertGrep " : /.*/libc.so" "$auditfile" + # Ensure the got-audit did not report any errors + rlAssertNotGrep " :: ERROR" "$auditfile" + rlRun "cp '$auditfile' '$TMT_TEST_DATA'/got-audit.txt" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "systemctl stop --user gnome-remote-desktop-headless" + rlRun "popd" + rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tests/main.fmf b/tests/main.fmf new file mode 100644 index 0000000..f225a72 --- /dev/null +++ b/tests/main.fmf @@ -0,0 +1,2 @@ +test: ./runtest.sh +framework: beakerlib