From bdf162537e3e1d779ddecfaa1190d91cc04a33e3 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Fri, 4 Oct 2019 08:54:42 -0700 Subject: [PATCH] Backport clipboard-race patches for #1755038 --- ...-vdagent-fix-memory-leak-of-g_memdup.patch | 57 ++++ 0002-x11-randr-use-glib-s-MAX-and-MIN.patch | 54 ++++ ...est-fix-for-address-of-packed-member.patch | 74 +++++ ...ple-fix-for-address-of-packed-member.patch | 53 ++++ ...-randr-Avoid-passing-XEvent-as-value.patch | 69 +++++ 0006-x11-Avoid-passing-XEvent-as-value.patch | 158 +++++++++++ 0007-x11-Constify-XEvent-argument.patch | 106 +++++++ ...ve-g_list_length-on-compare_addresse.patch | 264 ++++++++++++++++++ ...-to-make-code-scanners-not-giving-wa.patch | 54 ++++ ...id-false-positive-on-g_clear_pointer.patch | 142 ++++++++++ 0011-covscan-initialize-argv-s-copy.patch | 88 ++++++ ...omment-on-false-positive-on-g_memdup.patch | 38 +++ ...le_fds-make-read-and-write-code-cons.patch | 41 +++ 0014-Add-a-.gitpublish.patch | 30 ++ 0015-configure-bump-gtk-3.22.patch | 34 +++ ...rd-remove-vdagent-selection-id-usage.patch | 72 +++++ 0017-configure-depend-on-gobject.patch | 91 ++++++ 0018-configure-bump-gobject-2.50.patch | 39 +++ 0019-vdagent-use-G_OPTION_FLAG_NONE.patch | 70 +++++ ...pboard-gobject-ify-VDAgentClipboards.patch | 183 ++++++++++++ ...board-filter-out-only-our-own-events.patch | 48 ++++ ...-send-release-when-no-immediate-grab.patch | 82 ++++++ ...-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch | 120 ++++++++ spice-vdagent.spec | 41 ++- 24 files changed, 2006 insertions(+), 2 deletions(-) create mode 100644 0001-vdagent-fix-memory-leak-of-g_memdup.patch create mode 100644 0002-x11-randr-use-glib-s-MAX-and-MIN.patch create mode 100644 0003-x11-randr-simplest-fix-for-address-of-packed-member.patch create mode 100644 0004-vdagent-simple-fix-for-address-of-packed-member.patch create mode 100644 0005-x11-randr-Avoid-passing-XEvent-as-value.patch create mode 100644 0006-x11-Avoid-passing-XEvent-as-value.patch create mode 100644 0007-x11-Constify-XEvent-argument.patch create mode 100644 0008-device-info-remove-g_list_length-on-compare_addresse.patch create mode 100644 0009-x11-Change-check-to-make-code-scanners-not-giving-wa.patch create mode 100644 0010-covscan-avoid-false-positive-on-g_clear_pointer.patch create mode 100644 0011-covscan-initialize-argv-s-copy.patch create mode 100644 0012-covscan-add-comment-on-false-positive-on-g_memdup.patch create mode 100644 0013-virtio-port-handle_fds-make-read-and-write-code-cons.patch create mode 100644 0014-Add-a-.gitpublish.patch create mode 100644 0015-configure-bump-gtk-3.22.patch create mode 100644 0016-clipboard-remove-vdagent-selection-id-usage.patch create mode 100644 0017-configure-depend-on-gobject.patch create mode 100644 0018-configure-bump-gobject-2.50.patch create mode 100644 0019-vdagent-use-G_OPTION_FLAG_NONE.patch create mode 100644 0020-clipboard-gobject-ify-VDAgentClipboards.patch create mode 100644 0021-clipboard-filter-out-only-our-own-events.patch create mode 100644 0022-clipboard-only-send-release-when-no-immediate-grab.patch create mode 100644 0023-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch diff --git a/0001-vdagent-fix-memory-leak-of-g_memdup.patch b/0001-vdagent-fix-memory-leak-of-g_memdup.patch new file mode 100644 index 0000000..bf31af7 --- /dev/null +++ b/0001-vdagent-fix-memory-leak-of-g_memdup.patch @@ -0,0 +1,57 @@ +From b6fde1641a47c13b151b20c8e0db03cf7da45d9f Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 12 Jul 2019 11:12:37 +0200 +Subject: [PATCH 01/23] vdagent: fix memory leak of g_memdup() + +Found by covscan: + + | spice-vdagent-0.19.0/src/vdagent/vdagent.c:432:9: warning: Potential leak of memory pointed to by 'orig_argv' + | # g_printerr("Invalid arguments, %s\n", error->message); + | # ^ + | spice-vdagent-0.19.0/src/vdagent/vdagent.c:418:24: note: Memory is allocated + | # char **orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/vdagent.c:431:9: note: Assuming 'error' is not equal to NULL + | # if (error != NULL) { + | # ^~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/vdagent.c:431:5: note: Taking true branch + | # if (error != NULL) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/vdagent.c:432:9: note: Potential leak of memory pointed to by 'orig_argv' + | # g_printerr("Invalid arguments, %s\n", error->message); + | # ^ + | # 430| + | # 431| if (error != NULL) { + | # 432|-> g_printerr("Invalid arguments, %s\n", error->message); + | # 433| g_clear_error(&error); + | # 434| return -1; + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagent/vdagent.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index 13ef29f..d799d1f 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -431,6 +431,7 @@ int main(int argc, char *argv[]) + if (error != NULL) { + g_printerr("Invalid arguments, %s\n", error->message); + g_clear_error(&error); ++ g_free(orig_argv); + return -1; + } + +@@ -446,6 +447,7 @@ int main(int argc, char *argv[]) + + if (!g_file_test(portdev, G_FILE_TEST_EXISTS)) { + g_debug("vdagent virtio channel %s does not exist, exiting", portdev); ++ g_free(orig_argv); + return 0; + } + +-- +2.23.0 + diff --git a/0002-x11-randr-use-glib-s-MAX-and-MIN.patch b/0002-x11-randr-use-glib-s-MAX-and-MIN.patch new file mode 100644 index 0000000..4617b82 --- /dev/null +++ b/0002-x11-randr-use-glib-s-MAX-and-MIN.patch @@ -0,0 +1,54 @@ +From 70c5908f8c46a0cd53cca109ecc0c56ff5b33d77 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 12 Jul 2019 11:12:39 +0200 +Subject: [PATCH 02/23] x11-randr: use glib's MAX and MIN + +Since 2861868 "randr: remove monitors.xml on auto-configuration" in +2015-04-10 by Marc-Andre Lureau this +file includes glib.h and can remove those helpers. + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagent/x11-randr.c | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c +index 88857c8..d000e28 100644 +--- a/src/vdagent/x11-randr.c ++++ b/src/vdagent/x11-randr.c +@@ -555,16 +555,6 @@ int vdagent_x11_randr_handle_event(struct vdagent_x11 *x11, + return handled; + } + +-static int min_int(int x, int y) +-{ +- return x > y ? y : x; +-} +- +-static int max_int(int x, int y) +-{ +- return x > y ? x : y; +-} +- + static int constrain_to_range(int low, int *val, int high) + { + if (low <= *val && *val <= high) { +@@ -631,10 +621,10 @@ static void zero_base_monitors(struct vdagent_x11 *x11, + mon_width = (int *)&mon_config->monitors[i].width; + mon_height = (int *)&mon_config->monitors[i].height; + constrain_to_screen(x11, mon_width, mon_height); +- min_x = min_int(mon_config->monitors[i].x, min_x); +- min_y = min_int(mon_config->monitors[i].y, min_y); +- max_x = max_int(mon_config->monitors[i].x + *mon_width, max_x); +- max_y = max_int(mon_config->monitors[i].y + *mon_height, max_y); ++ min_x = MIN(mon_config->monitors[i].x, min_x); ++ min_y = MIN(mon_config->monitors[i].y, min_y); ++ max_x = MAX(mon_config->monitors[i].x + *mon_width, max_x); ++ max_y = MAX(mon_config->monitors[i].y + *mon_height, max_y); + } + if (min_x != 0 || min_y != 0) { + syslog(LOG_ERR, "%s: agent config %d,%d rooted, adjusting to 0,0.", +-- +2.23.0 + diff --git a/0003-x11-randr-simplest-fix-for-address-of-packed-member.patch b/0003-x11-randr-simplest-fix-for-address-of-packed-member.patch new file mode 100644 index 0000000..b803619 --- /dev/null +++ b/0003-x11-randr-simplest-fix-for-address-of-packed-member.patch @@ -0,0 +1,74 @@ +From 7976dc31af511315fa7b83cfbb1e3bf4b613f84b Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 12 Jul 2019 11:12:41 +0200 +Subject: [PATCH 03/23] x11-randr: simplest fix for address-of-packed-member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The struct type for width/height is uint32_t while we are trying to +access and change it with int* - code can be improved a bit in following +patches but this one fixes the warning by copying the value from the +struct and copying back new value afterwards. + +Also: +- Moved variables to internal scope; +- Added braces to inner if; + + > src/vdagent/x11-randr.c: In function ‘zero_base_monitors’: + > src/vdagent/x11-randr.c:621:28: error: taking address of packed member of + > ‘struct VDAgentMonConfig’ may result in an unaligned pointer value + > [-Werror=address-of-packed-member] + > 621 | mon_width = (int *)&mon_config->monitors[i].width; + > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > src/vdagent/x11-randr.c:622:29: error: taking address of packed member of + > ‘struct VDAgentMonConfig’ may result in an unaligned pointer value + > [-Werror=address-of-packed-member] + > 622 | mon_height = (int *)&mon_config->monitors[i].height; + > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagent/x11-randr.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c +index d000e28..4b022d6 100644 +--- a/src/vdagent/x11-randr.c ++++ b/src/vdagent/x11-randr.c +@@ -611,20 +611,24 @@ static void zero_base_monitors(struct vdagent_x11 *x11, + int *width, int *height) + { + int i, min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; +- int *mon_height, *mon_width; + + for (i = 0; i < mon_config->num_of_monitors; i++) { +- if (!monitor_enabled(&mon_config->monitors[i])) ++ int mon_height, mon_width; ++ ++ if (!monitor_enabled(&mon_config->monitors[i])) { + continue; ++ } + mon_config->monitors[i].x &= ~7; + mon_config->monitors[i].width &= ~7; +- mon_width = (int *)&mon_config->monitors[i].width; +- mon_height = (int *)&mon_config->monitors[i].height; +- constrain_to_screen(x11, mon_width, mon_height); ++ mon_width = mon_config->monitors[i].width; ++ mon_height = mon_config->monitors[i].height; ++ constrain_to_screen(x11, &mon_width, &mon_height); + min_x = MIN(mon_config->monitors[i].x, min_x); + min_y = MIN(mon_config->monitors[i].y, min_y); +- max_x = MAX(mon_config->monitors[i].x + *mon_width, max_x); +- max_y = MAX(mon_config->monitors[i].y + *mon_height, max_y); ++ max_x = MAX(mon_config->monitors[i].x + mon_width, max_x); ++ max_y = MAX(mon_config->monitors[i].y + mon_height, max_y); ++ mon_config->monitors[i].width = mon_width; ++ mon_config->monitors[i].height = mon_height; + } + if (min_x != 0 || min_y != 0) { + syslog(LOG_ERR, "%s: agent config %d,%d rooted, adjusting to 0,0.", +-- +2.23.0 + diff --git a/0004-vdagent-simple-fix-for-address-of-packed-member.patch b/0004-vdagent-simple-fix-for-address-of-packed-member.patch new file mode 100644 index 0000000..b1c37db --- /dev/null +++ b/0004-vdagent-simple-fix-for-address-of-packed-member.patch @@ -0,0 +1,53 @@ +From 6bfbd03e83fc8fcf783d4431607d7d6129af58b0 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 12 Jul 2019 11:12:42 +0200 +Subject: [PATCH 04/23] vdagent: simple fix for address-of-packed-member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Seems to be a false positive but as this message only happens when user +client connects, we can copy this array to make compiling warn free. + + > src/vdagent/vdagent.c: In function ‘daemon_read_complete’: + > src/vdagent/vdagent.c:226:71: error: taking address of packed member of + > ‘struct VDAgentAudioVolumeSync’ may result in an unaligned pointer + > value [-Werror=address-of-packed-member] + > 226 | vdagent_audio_playback_sync(avs->mute, avs->nchannels, avs->volume); + > | ~~~^~~~~~~~ + > src/vdagent/vdagent.c:228:69: error: taking address of packed member of + > ‘struct VDAgentAudioVolumeSync’ may result in an unaligned pointer + > value [-Werror=address-of-packed-member] + > 228 | vdagent_audio_record_sync(avs->mute, avs->nchannels, avs->volume); + > | ~~~^~~~~~~~ + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagent/vdagent.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index d799d1f..0e2e73e 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -222,11 +222,14 @@ static void daemon_read_complete(struct udscs_connection **connp, + break; + case VDAGENTD_AUDIO_VOLUME_SYNC: { + VDAgentAudioVolumeSync *avs = (VDAgentAudioVolumeSync *)data; ++ uint16_t *volume = g_memdup(avs->volume, sizeof(uint16_t) * avs->nchannels); ++ + if (avs->is_playback) { +- vdagent_audio_playback_sync(avs->mute, avs->nchannels, avs->volume); ++ vdagent_audio_playback_sync(avs->mute, avs->nchannels, volume); + } else { +- vdagent_audio_record_sync(avs->mute, avs->nchannels, avs->volume); ++ vdagent_audio_record_sync(avs->mute, avs->nchannels, volume); + } ++ g_free(volume); + break; + } + case VDAGENTD_FILE_XFER_DATA: +-- +2.23.0 + diff --git a/0005-x11-randr-Avoid-passing-XEvent-as-value.patch b/0005-x11-randr-Avoid-passing-XEvent-as-value.patch new file mode 100644 index 0000000..a4d3581 --- /dev/null +++ b/0005-x11-randr-Avoid-passing-XEvent-as-value.patch @@ -0,0 +1,69 @@ +From b6dfef73f2926c65ed146eea6ab061dd87d77f10 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Wed, 19 Dec 2018 18:25:51 +0000 +Subject: [PATCH 05/23] x11-randr: Avoid passing XEvent as value + +The structure is not that small and is not necessary to copy +the value. +This also removed a Coverity warning. + +Signed-off-by: Frediano Ziglio +Acked-by: Victor Toso +--- + src/vdagent/x11-priv.h | 2 +- + src/vdagent/x11-randr.c | 8 ++++---- + src/vdagent/x11.c | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h +index 99676d2..730b9b3 100644 +--- a/src/vdagent/x11-priv.h ++++ b/src/vdagent/x11-priv.h +@@ -152,7 +152,7 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, + void vdagent_x11_randr_handle_root_size_change(struct vdagent_x11 *x11, + int screen, int width, int height); + int vdagent_x11_randr_handle_event(struct vdagent_x11 *x11, +- XEvent event); ++ const XEvent *event); + void vdagent_x11_set_error_handler(struct vdagent_x11 *x11, + int (*handler)(Display *, XErrorEvent *)); + int vdagent_x11_restore_error_handler(struct vdagent_x11 *x11); +diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c +index 4b022d6..3fb7a68 100644 +--- a/src/vdagent/x11-randr.c ++++ b/src/vdagent/x11-randr.c +@@ -529,14 +529,14 @@ void vdagent_x11_randr_handle_root_size_change(struct vdagent_x11 *x11, + } + + int vdagent_x11_randr_handle_event(struct vdagent_x11 *x11, +- XEvent event) ++ const XEvent *event) + { + int handled = TRUE; + +- switch (event.type - x11->xrandr_event_base) { ++ switch (event->type - x11->xrandr_event_base) { + case RRScreenChangeNotify: { +- XRRScreenChangeNotifyEvent *sce = +- (XRRScreenChangeNotifyEvent *) &event; ++ const XRRScreenChangeNotifyEvent *sce = ++ (const XRRScreenChangeNotifyEvent *) event; + vdagent_x11_randr_handle_root_size_change(x11, 0, + sce->width, sce->height); + break; +diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c +index c2515a8..61d7c69 100644 +--- a/src/vdagent/x11.c ++++ b/src/vdagent/x11.c +@@ -545,7 +545,7 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + } + #endif + +- if (vdagent_x11_randr_handle_event(x11, event)) ++ if (vdagent_x11_randr_handle_event(x11, &event)) + return; + + switch (event.type) { +-- +2.23.0 + diff --git a/0006-x11-Avoid-passing-XEvent-as-value.patch b/0006-x11-Avoid-passing-XEvent-as-value.patch new file mode 100644 index 0000000..9d9eaaf --- /dev/null +++ b/0006-x11-Avoid-passing-XEvent-as-value.patch @@ -0,0 +1,158 @@ +From 3522667bfac147f4f959025ccf12ea1d99cc1f75 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Wed, 19 Dec 2018 18:28:38 +0000 +Subject: [PATCH 06/23] x11: Avoid passing XEvent as value + +The structure is not that small and is not necessary to copy +the value. +This also removed a Coverity warning. + +Signed-off-by: Frediano Ziglio +Acked-by: Victor Toso +--- + src/vdagent/x11.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c +index 61d7c69..42f42e7 100644 +--- a/src/vdagent/x11.c ++++ b/src/vdagent/x11.c +@@ -494,23 +494,23 @@ static int vdagent_x11_get_clipboard_selection(struct vdagent_x11 *x11, + } + #endif + +-static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) ++static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent *event) + { + int i, handled = 0; + #ifndef WITH_GTK + uint8_t selection; + +- if (event.type == x11->xfixes_event_base) { ++ if (event->type == x11->xfixes_event_base) { + union { + XEvent ev; + XFixesSelectionNotifyEvent xfev; + } ev; + +- if (vdagent_x11_get_clipboard_selection(x11, &event, &selection)) { ++ if (vdagent_x11_get_clipboard_selection(x11, event, &selection)) { + return; + } + +- ev.ev = event; ++ ev.ev = *event; + switch (ev.xfev.subtype) { + case XFixesSetSelectionOwnerNotify: + break; +@@ -521,7 +521,7 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + break; + default: + VSELPRINTF("unexpected xfix event subtype %d window %d", +- (int)ev.xfev.subtype, (int)event.xany.window); ++ (int)ev.xfev.subtype, (int)event->xany.window); + return; + } + VSELPRINTF("New selection owner: %u", (unsigned int)ev.xfev.owner); +@@ -545,20 +545,20 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + } + #endif + +- if (vdagent_x11_randr_handle_event(x11, &event)) ++ if (vdagent_x11_randr_handle_event(x11, event)) + return; + +- switch (event.type) { ++ switch (event->type) { + case ConfigureNotify: + for (i = 0; i < x11->screen_count; i++) +- if (event.xconfigure.window == x11->root_window[i]) ++ if (event->xconfigure.window == x11->root_window[i]) + break; + if (i == x11->screen_count) + break; + + handled = 1; + vdagent_x11_randr_handle_root_size_change(x11, i, +- event.xconfigure.width, event.xconfigure.height); ++ event->xconfigure.width, event->xconfigure.height); + break; + case MappingNotify: + /* These are uninteresting */ +@@ -566,21 +566,21 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + break; + #ifndef WITH_GTK + case SelectionNotify: +- if (event.xselection.target == x11->targets_atom) +- vdagent_x11_handle_targets_notify(x11, &event); ++ if (event->xselection.target == x11->targets_atom) ++ vdagent_x11_handle_targets_notify(x11, event); + else +- vdagent_x11_handle_selection_notify(x11, &event, 0); ++ vdagent_x11_handle_selection_notify(x11, event, 0); + + handled = 1; + break; + case PropertyNotify: + if (x11->expect_property_notify && +- event.xproperty.state == PropertyNewValue) { +- vdagent_x11_handle_selection_notify(x11, &event, 1); ++ event->xproperty.state == PropertyNewValue) { ++ vdagent_x11_handle_selection_notify(x11, event, 1); + } + if (x11->selection_req_data && +- event.xproperty.state == PropertyDelete) { +- vdagent_x11_handle_property_delete_notify(x11, &event); ++ event->xproperty.state == PropertyDelete) { ++ vdagent_x11_handle_property_delete_notify(x11, event); + } + /* Always mark as handled, since we cannot unselect input for property + notifications once we are done with handling the incr transfer. */ +@@ -594,7 +594,7 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + case SelectionRequest: { + struct vdagent_x11_selection_request *req, *new_req; + +- if (vdagent_x11_get_clipboard_selection(x11, &event, &selection)) { ++ if (vdagent_x11_get_clipboard_selection(x11, event, &selection)) { + return; + } + +@@ -606,7 +606,7 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + + handled = 1; + +- new_req->event = event; ++ new_req->event = *event; + new_req->selection = selection; + new_req->next = NULL; + +@@ -628,7 +628,7 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event) + } + if (!handled && x11->debug) + syslog(LOG_DEBUG, "unhandled x11 event, type %d, window %d", +- (int)event.type, (int)event.xany.window); ++ (int)event->type, (int)event->xany.window); + } + + void vdagent_x11_do_read(struct vdagent_x11 *x11) +@@ -637,7 +637,7 @@ void vdagent_x11_do_read(struct vdagent_x11 *x11) + + while (XPending(x11->display)) { + XNextEvent(x11->display, &event); +- vdagent_x11_handle_event(x11, event); ++ vdagent_x11_handle_event(x11, &event); + } + } + +@@ -1370,7 +1370,7 @@ void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection) + XSync(x11->display, False); + while (XCheckTypedEvent(x11->display, x11->xfixes_event_base, + &event)) +- vdagent_x11_handle_event(x11, event); ++ vdagent_x11_handle_event(x11, &event); + + /* Note no need to do a set_clipboard_owner(owner_none) here, as that is + already done by processing the XFixesSetSelectionOwnerNotify event. */ +-- +2.23.0 + diff --git a/0007-x11-Constify-XEvent-argument.patch b/0007-x11-Constify-XEvent-argument.patch new file mode 100644 index 0000000..172cb07 --- /dev/null +++ b/0007-x11-Constify-XEvent-argument.patch @@ -0,0 +1,106 @@ +From af8d1948b1acc7baeb24f58efd52e5bbe9aa2441 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Wed, 19 Dec 2018 22:37:56 +0000 +Subject: [PATCH 07/23] x11: Constify XEvent argument + +No reasons to have it mutable. + +Signed-off-by: Frediano Ziglio +Acked-by: Victor Toso +--- + src/vdagent/x11.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c +index 42f42e7..966ea62 100644 +--- a/src/vdagent/x11.c ++++ b/src/vdagent/x11.c +@@ -59,12 +59,12 @@ int vdagent_x11_caught_error; + + #ifndef WITH_GTK + static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11, +- XEvent *event, int incr); ++ const XEvent *event, int incr); + static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11); + static void vdagent_x11_handle_targets_notify(struct vdagent_x11 *x11, +- XEvent *event); ++ const XEvent *event); + static void vdagent_x11_handle_property_delete_notify(struct vdagent_x11 *x11, +- XEvent *del_event); ++ const XEvent *del_event); + static void vdagent_x11_send_selection_notify(struct vdagent_x11 *x11, + Atom prop, struct vdagent_x11_selection_request *request); + static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11, +@@ -465,12 +465,13 @@ static int vdagent_x11_get_clipboard_atom(struct vdagent_x11 *x11, uint8_t selec + } + + static int vdagent_x11_get_clipboard_selection(struct vdagent_x11 *x11, +- XEvent *event, uint8_t *selection) ++ const XEvent *event, uint8_t *selection) + { + Atom atom; + + if (event->type == x11->xfixes_event_base) { +- XFixesSelectionNotifyEvent *xfev = (XFixesSelectionNotifyEvent *)event; ++ const XFixesSelectionNotifyEvent *xfev = ++ (const XFixesSelectionNotifyEvent *)event; + atom = xfev->selection; + } else if (event->type == SelectionNotify) { + atom = event->xselection.selection; +@@ -494,7 +495,7 @@ static int vdagent_x11_get_clipboard_selection(struct vdagent_x11 *x11, + } + #endif + +-static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent *event) ++static void vdagent_x11_handle_event(struct vdagent_x11 *x11, const XEvent *event) + { + int i, handled = 0; + #ifndef WITH_GTK +@@ -650,7 +651,7 @@ static const char *vdagent_x11_get_atom_name(struct vdagent_x11 *x11, Atom a) + return XGetAtomName(x11->display, a); + } + +-static int vdagent_x11_get_selection(struct vdagent_x11 *x11, XEvent *event, ++static int vdagent_x11_get_selection(struct vdagent_x11 *x11, const XEvent *event, + uint8_t selection, Atom type, Atom prop, int format, + unsigned char **data_ret, int incr) + { +@@ -842,7 +843,7 @@ static void vdagent_x11_handle_conversion_request(struct vdagent_x11 *x11) + } + + static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11, +- XEvent *event, int incr) ++ const XEvent *event, int incr) + { + int len = 0; + unsigned char *data = NULL; +@@ -927,7 +928,7 @@ static void vdagent_x11_print_targets(struct vdagent_x11 *x11, + } + + static void vdagent_x11_handle_targets_notify(struct vdagent_x11 *x11, +- XEvent *event) ++ const XEvent *event) + { + int i, len; + Atom atom, *atoms = NULL; +@@ -1026,7 +1027,7 @@ static void vdagent_x11_send_selection_notify(struct vdagent_x11 *x11, + } + + static void vdagent_x11_send_targets(struct vdagent_x11 *x11, +- uint8_t selection, XEvent *event) ++ uint8_t selection, const XEvent *event) + { + Atom prop, targets[256] = { x11->targets_atom, }; + int i, j, k, target_count = 1; +@@ -1123,7 +1124,7 @@ static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11) + } + + static void vdagent_x11_handle_property_delete_notify(struct vdagent_x11 *x11, +- XEvent *del_event) ++ const XEvent *del_event) + { + XEvent *sel_event; + int len; +-- +2.23.0 + diff --git a/0008-device-info-remove-g_list_length-on-compare_addresse.patch b/0008-device-info-remove-g_list_length-on-compare_addresse.patch new file mode 100644 index 0000000..ef3322c --- /dev/null +++ b/0008-device-info-remove-g_list_length-on-compare_addresse.patch @@ -0,0 +1,264 @@ +From 66935d134e1f359eda5cfac053b0bf716811670a Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Fri, 12 Jul 2019 11:12:36 +0200 +Subject: [PATCH 08/23] device-info: remove g_list_length() on + compare_addresses() + +The g_list_length() function does iterate over both lists to compare +its length. Considering that we use this to check for true/false and +we will iterate again on both lists, we can do so once. + +This also avoids covscan/clang warnings: + + | spice-vdagent-0.19.0/src/vdagent/device-info.c:216:27: warning: Access to field 'data' results in a dereference of a null pointer (loaded from variable 'lb') + | # PciDevice *devb = lb->data; + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:397:5: note: Taking false branch + | # if (!user_pci_addr) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:407:22: note: Calling 'find_device_at_pci_address' + | # char *dev_path = find_device_at_pci_address(user_pci_addr, &vendor_id, &device_id); + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:329:5: note: Taking true branch + | # g_return_val_if_fail(pci_addr != NULL, NULL); + | # ^ + | /usr/include/glib-2.0/glib/gmessages.h:594:9: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:385:43: note: expanded from macro 'G_LIKELY' + | ##define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1)) + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:379:4: note: expanded from macro '_G_BOOLEAN_EXPR' + | # if (expr) \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:329:5: note: Taking true branch + | /usr/include/glib-2.0/glib/gmessages.h:594:6: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:329:5: note: Loop condition is false. Exiting loop + | /usr/include/glib-2.0/glib/gmessages.h:593:40: note: expanded from macro 'g_return_val_if_fail' + | ##define g_return_val_if_fail(expr,val) G_STMT_START{ \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:346:23: note: expanded from macro 'G_STMT_START' + | ##define G_STMT_START do + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:330:5: note: Taking true branch + | # g_return_val_if_fail(device_id != NULL, NULL); + | # ^ + | /usr/include/glib-2.0/glib/gmessages.h:594:9: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:385:43: note: expanded from macro 'G_LIKELY' + | ##define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1)) + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:379:4: note: expanded from macro '_G_BOOLEAN_EXPR' + | # if (expr) \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:330:5: note: Taking true branch + | /usr/include/glib-2.0/glib/gmessages.h:594:6: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:330:5: note: Loop condition is false. Exiting loop + | /usr/include/glib-2.0/glib/gmessages.h:593:40: note: expanded from macro 'g_return_val_if_fail' + | ##define g_return_val_if_fail(expr,val) G_STMT_START{ \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:346:23: note: expanded from macro 'G_STMT_START' + | ##define G_STMT_START do + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:331:5: note: Taking true branch + | # g_return_val_if_fail(vendor_id != NULL, NULL); + | # ^ + | /usr/include/glib-2.0/glib/gmessages.h:594:9: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:385:43: note: expanded from macro 'G_LIKELY' + | ##define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1)) + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:379:4: note: expanded from macro '_G_BOOLEAN_EXPR' + | # if (expr) \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:331:5: note: Taking true branch + | /usr/include/glib-2.0/glib/gmessages.h:594:6: note: expanded from macro 'g_return_val_if_fail' + | # if G_LIKELY(expr) { } else \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:331:5: note: Loop condition is false. Exiting loop + | /usr/include/glib-2.0/glib/gmessages.h:593:40: note: expanded from macro 'g_return_val_if_fail' + | ##define g_return_val_if_fail(expr,val) G_STMT_START{ \ + | # ^ + | /usr/include/glib-2.0/glib/gmacros.h:346:23: note: expanded from macro 'G_STMT_START' + | ##define G_STMT_START do + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:334:5: note: Loop condition is true. Entering loop body + | # for (int i = 0; i < 10; ++i) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:340:13: note: Assuming the condition is false + | # if (stat(dev_path, &buf) != 0) { + | # ^~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:340:9: note: Taking false branch + | # if (stat(dev_path, &buf) != 0) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:355:13: note: Assuming the condition is false + | # if (realpath(sys_path, device_link) == NULL) { + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:355:9: note: Taking false branch + | # if (realpath(sys_path, device_link) == NULL) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:361:36: note: Calling 'parse_pci_address_from_sysfs_path' + | # PciAddress *drm_pci_addr = parse_pci_address_from_sysfs_path(device_link); + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:129:9: note: Assuming 'pos' is non-null + | # if (!pos) { + | # ^~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:129:5: note: Taking false branch + | # if (!pos) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:136:9: note: Assuming 'pos' is non-null + | # if (!pos) { + | # ^~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:136:5: note: Taking false branch + | # if (!pos) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:142:9: note: Assuming 'pos' is non-null + | # if (!pos) { + | # ^~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:142:5: note: Taking false branch + | # if (!pos) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:146:27: note: Calling 'pci_address_new' + | # PciAddress *address = pci_address_new(); + | # ^~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:61:12: note: Taking false branch + | # return g_new0(PciAddress, 1); + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:279:42: note: expanded from macro 'g_new0' + | ##define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:211:4: note: expanded from macro '_G_NEW' + | # if (__s == 1) \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:61:12: note: Left side of '&&' is false + | /usr/include/glib-2.0/glib/gmem.h:279:42: note: expanded from macro 'g_new0' + | ##define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:213:40: note: expanded from macro '_G_NEW' + | # else if (__builtin_constant_p (__n) && \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:61:12: note: Null pointer value stored to field 'devices' + | # return g_new0(PciAddress, 1); + | # ^~~~~~~~~~~~~~~~~~~~~ + | /usr/include/glib-2.0/glib/gmem.h:279:42: note: expanded from macro 'g_new0' + | ##define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | /usr/include/glib-2.0/glib/gmem.h:217:12: note: expanded from macro '_G_NEW' + | # __p = g_##func##_n (__n, __s); \ + | # ^~~~~~~~~~~~~~~~~~~~~~~ + | :76:1: note: expanded from here + | #g_malloc0_n + | #^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:146:27: note: Returning from 'pci_address_new' + | # PciAddress *address = pci_address_new(); + | # ^~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:149:5: note: Loop condition is true. Entering loop body + | # while (pos) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:150:26: note: Taking false branch + | # PciDevice *dev = g_new0(PciDevice, 1); + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:279:42: note: expanded from macro 'g_new0' + | ##define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:211:4: note: expanded from macro '_G_NEW' + | # if (__s == 1) \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:150:26: note: Left side of '&&' is false + | /usr/include/glib-2.0/glib/gmem.h:279:42: note: expanded from macro 'g_new0' + | ##define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) + | # ^ + | /usr/include/glib-2.0/glib/gmem.h:213:40: note: expanded from macro '_G_NEW' + | # else if (__builtin_constant_p (__n) && \ + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:152:9: note: Taking true branch + | # if (!parse_pci_device(pos + 1, next, dev)) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:154:13: note: Execution continues on line 159 + | # break; + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:361:36: note: Returning from 'parse_pci_address_from_sysfs_path' + | # PciAddress *drm_pci_addr = parse_pci_address_from_sysfs_path(device_link); + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:362:9: note: Taking false branch + | # if (!drm_pci_addr) { + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:367:14: note: Calling 'compare_addresses' + | # if (!compare_addresses(pci_addr, drm_pci_addr)) { + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:207:11: note: Assuming the condition is true + | # if (!(a->domain == b->domain + | # ^~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:207:11: note: Left side of '&&' is true + | spice-vdagent-0.19.0/src/vdagent/device-info.c:208:12: note: Assuming the condition is true + | # && g_list_length(a->devices) == g_list_length(b->devices))) { + | # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:207:5: note: Taking false branch + | # if (!(a->domain == b->domain + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:212:35: note: 'lb' initialized to a null pointer value + | # for (GList *la = a->devices, *lb = b->devices; + | # ^~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:213:10: note: Assuming 'la' is not equal to NULL + | # la != NULL; + | # ^~~~~~~~~~ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:212:5: note: Loop condition is true. Entering loop body + | # for (GList *la = a->devices, *lb = b->devices; + | # ^ + | spice-vdagent-0.19.0/src/vdagent/device-info.c:216:27: note: Access to field 'data' results in a dereference of a null pointer (loaded from variable 'lb') + | # PciDevice *devb = lb->data; + | # ^~ + | # 214| la = la->next, lb = lb->next) { + | # 215| PciDevice *deva = la->data; + | # 216|-> PciDevice *devb = lb->data; + | # 217| + | # 218| if (deva->slot != devb->slot + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagent/device-info.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c +index 4983543..6b0e28f 100644 +--- a/src/vdagent/device-info.c ++++ b/src/vdagent/device-info.c +@@ -204,13 +204,13 @@ static PciAddress* parse_pci_address_from_spice(char *input) + static bool compare_addresses(PciAddress *a, PciAddress *b) + { + // only check domain, slot, and function +- if (!(a->domain == b->domain +- && g_list_length(a->devices) == g_list_length(b->devices))) { ++ if (a->domain != b->domain) { + return false; + } + +- for (GList *la = a->devices, *lb = b->devices; +- la != NULL; ++ const GList *la, *lb; ++ for (la = a->devices, lb = b->devices; ++ la != NULL && lb != NULL; + la = la->next, lb = lb->next) { + PciDevice *deva = la->data; + PciDevice *devb = lb->data; +@@ -220,7 +220,9 @@ static bool compare_addresses(PciAddress *a, PciAddress *b) + return false; + } + } +- return true; ++ ++ /* True only if both have the same length */ ++ return (la == NULL && lb == NULL); + } + + // Connector type names from xorg modesetting driver +-- +2.23.0 + diff --git a/0009-x11-Change-check-to-make-code-scanners-not-giving-wa.patch b/0009-x11-Change-check-to-make-code-scanners-not-giving-wa.patch new file mode 100644 index 0000000..32b428e --- /dev/null +++ b/0009-x11-Change-check-to-make-code-scanners-not-giving-wa.patch @@ -0,0 +1,54 @@ +From 0b94306d2c1305aee1c56bc9f927f95371484844 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Sat, 20 Jul 2019 14:42:10 +0100 +Subject: [PATCH 09/23] x11: Change check to make code scanners not giving + warning + +Some code scanners (both Coverity and clang one) report that +prev_sel/prev_cond could be unreferenced while NULL. +Change condition to make clear a NULL pointer is not used. + +Signed-off-by: Frediano Ziglio +Acked-by: Victor Toso +--- + src/vdagent/x11.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c +index 966ea62..6f83849 100644 +--- a/src/vdagent/x11.c ++++ b/src/vdagent/x11.c +@@ -392,7 +392,7 @@ static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11, + once = 0; + } + vdagent_x11_send_selection_notify(x11, None, curr_sel); +- if (curr_sel == x11->selection_req) { ++ if (prev_sel == NULL) { + x11->selection_req = next_sel; + free(x11->selection_req_data); + x11->selection_req_data = NULL; +@@ -400,7 +400,6 @@ static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11, + x11->selection_req_data_size = 0; + x11->selection_req_atom = None; + } else { +- // coverity[var_deref_op] if it is not the first there's a previous + prev_sel->next = next_sel; + } + free(curr_sel); +@@ -424,12 +423,11 @@ static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11, + if (x11->vdagentd) + udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_DATA, selection, + VD_AGENT_CLIPBOARD_NONE, NULL, 0); +- if (curr_conv == x11->conversion_req) { ++ if (prev_conv == NULL) { + x11->conversion_req = next_conv; + x11->clipboard_data_size = 0; + x11->expect_property_notify = 0; + } else { +- // coverity[var_deref_op] if it is not the first there's a previous + prev_conv->next = next_conv; + } + free(curr_conv); +-- +2.23.0 + diff --git a/0010-covscan-avoid-false-positive-on-g_clear_pointer.patch b/0010-covscan-avoid-false-positive-on-g_clear_pointer.patch new file mode 100644 index 0000000..65eff19 --- /dev/null +++ b/0010-covscan-avoid-false-positive-on-g_clear_pointer.patch @@ -0,0 +1,142 @@ +From 83d2dbba246497408f2782854e1f021d334dfbc2 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Tue, 27 Aug 2019 10:59:30 +0200 +Subject: [PATCH 10/23] covscan: avoid false positive on g_clear_pointer() + +This is a CLANG_WARNING found by covscan. It is a false positive as +g_clear_pointer() does set vportp to NULL, meaning that the situation +described by covscan below should not be reached. Moving away from +g_clear_pointer() in this specific case just to make our tool happy. + +Covscan report: + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:458:9: warning: Use of memory after it is freed + > # if (wbuf->write_pos != wbuf->size) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:268:12: note: Assuming the condition is true + > # while (*vportp && (*vportp)->write_buf) + > # ^~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:268:12: note: Left side of '&&' is true + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:268:5: note: Loop condition is true. Entering loop body + > # while (*vportp && (*vportp)->write_buf) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:269:9: note: Calling 'vdagent_virtio_port_do_write' + > # vdagent_virtio_port_do_write(vportp); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:453:5: note: Taking false branch + > # if (!wbuf) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:458:9: note: Assuming the condition is false + > # if (wbuf->write_pos != wbuf->size) { + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:458:5: note: Taking false branch + > # if (wbuf->write_pos != wbuf->size) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:465:9: note: Assuming 'n' is < 0 + > # if (n < 0) { + > # ^~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:465:5: note: Taking true branch + > # if (n < 0) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:466:13: note: Assuming the condition is false + > # if (errno == EINTR) + > # ^~~~~~~~~~~~~~ + > /usr/include/errno.h:38:16: note: expanded from macro 'errno' + > ## define errno (*__errno_location ()) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:466:9: note: Taking false branch + > # if (errno == EINTR) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:469:9: note: Calling 'vdagent_virtio_port_destroy' + > # vdagent_virtio_port_destroy(vportp); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:130:5: note: Taking false branch + > # if (!vport) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:133:9: note: Assuming the condition is false + > # if (vport->disconnect_callback) + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:133:5: note: Taking false branch + > # if (vport->disconnect_callback) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:137:5: note: Loop condition is true. Entering loop body + > # while (wbuf) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:140:9: note: Memory is released + > # g_free(wbuf); + > # ^~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:137:5: note: Loop condition is false. Execution continues on line 144 + > # while (wbuf) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:144:5: note: Loop condition is true. Entering loop body + > # for (i = 0; i < VDP_END_PORT; i++) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:144:5: note: Loop condition is true. Entering loop body + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:144:5: note: Loop condition is true. Entering loop body + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:144:5: note: Loop condition is false. Execution continues on line 148 + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:149:5: note: Assuming '_p' is null + > # g_clear_pointer(vportp, g_free); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > /usr/include/glib-2.0/glib/gmem.h:124:9: note: expanded from macro 'g_clear_pointer' + > # if (_p) \ + > # ^~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:149:5: note: Taking false branch + > /usr/include/glib-2.0/glib/gmem.h:124:5: note: expanded from macro 'g_clear_pointer' + > # if (_p) \ + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:149:5: note: Loop condition is false. Exiting loop + > /usr/include/glib-2.0/glib/gmem.h:114:3: note: expanded from macro 'g_clear_pointer' + > # G_STMT_START { \ + > # ^ + > /usr/include/glib-2.0/glib/gmacros.h:346:23: note: expanded from macro 'G_STMT_START' + > ##define G_STMT_START do + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:469:9: note: Returning; memory was released + > # vdagent_virtio_port_destroy(vportp); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:269:9: note: Returning; memory was released + > # vdagent_virtio_port_do_write(vportp); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:268:12: note: Left side of '&&' is true + > # while (*vportp && (*vportp)->write_buf) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:268:5: note: Loop condition is true. Entering loop body + > # while (*vportp && (*vportp)->write_buf) + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:269:9: note: Calling 'vdagent_virtio_port_do_write' + > # vdagent_virtio_port_do_write(vportp); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:453:5: note: Taking false branch + > # if (!wbuf) { + > # ^ + > spice-vdagent-0.19.0/src/vdagentd/virtio-port.c:458:9: note: Use of memory after it is freed + > # if (wbuf->write_pos != wbuf->size) { + > # ^~~~~~~~~~~~~~~ + > # 456| } + > # 457| + > # 458|-> if (wbuf->write_pos != wbuf->size) { + > # 459| syslog(LOG_ERR, "do_write: buffer is incomplete!!"); + > # 460| return; + +Signed-off-by: Victor Toso +Acked-by: Frediano Ziglio +--- + src/vdagentd/virtio-port.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/vdagentd/virtio-port.c b/src/vdagentd/virtio-port.c +index b0556ce..3ae7f22 100644 +--- a/src/vdagentd/virtio-port.c ++++ b/src/vdagentd/virtio-port.c +@@ -146,7 +146,8 @@ void vdagent_virtio_port_destroy(struct vdagent_virtio_port **vportp) + } + + close(vport->fd); +- g_clear_pointer(vportp, g_free); ++ g_free(vport); ++ *vportp = NULL; + } + + int vdagent_virtio_port_fill_fds(struct vdagent_virtio_port *vport, +-- +2.23.0 + diff --git a/0011-covscan-initialize-argv-s-copy.patch b/0011-covscan-initialize-argv-s-copy.patch new file mode 100644 index 0000000..d8a8be0 --- /dev/null +++ b/0011-covscan-initialize-argv-s-copy.patch @@ -0,0 +1,88 @@ +From cedab5fe0e40e756a387013f59b257dd9f4f24cd Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Mon, 26 Aug 2019 17:03:22 +0200 +Subject: [PATCH 11/23] covscan: initialize argv's copy + +Otherwise we get a CLANG_WARNING due accessing garbage. + +Covscan report: + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:471:9: warning: 1st function call argument is an uninitialized value + > # execvp(orig_argv[0], orig_argv); + > # ^ ~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:421:24: note: Storing uninitialized value + > # char **orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:434:9: note: Assuming 'error' is equal to NULL + > # if (error != NULL) { + > # ^~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:434:5: note: Taking false branch + > # if (error != NULL) { + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:442:9: note: Assuming 'portdev' is not equal to NULL + > # if (portdev == NULL) + > # ^~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:442:5: note: Taking false branch + > # if (portdev == NULL) + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:445:9: note: Assuming 'vdagentd_socket' is not equal to NULL + > # if (vdagentd_socket == NULL) + > # ^~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:445:5: note: Taking false branch + > # if (vdagentd_socket == NULL) + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:448:30: note: Assuming 'do_daemonize' is 0 + > # openlog("spice-vdagent", do_daemonize ? LOG_PID : (LOG_PID | LOG_PERROR), + > # ^~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:448:30: note: '?' condition is false + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:451:9: note: Assuming the condition is false + > # if (!g_file_test(portdev, G_FILE_TEST_EXISTS)) { + > # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:451:5: note: Taking false branch + > # if (!g_file_test(portdev, G_FILE_TEST_EXISTS)) { + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:457:9: note: Assuming 'do_daemonize' is 0 + > # if (do_daemonize) + > # ^~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:457:5: note: Taking false branch + > # if (do_daemonize) + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:468:9: note: Assuming 'version_mismatch' is not equal to 0 + > # if (version_mismatch) { + > # ^~~~~~~~~~~~~~~~ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:468:5: note: Taking true branch + > # if (version_mismatch) { + > # ^ + > spice-vdagent-0.19.0/src/vdagent/vdagent.c:471:9: note: 1st function call argument is an uninitialized value + > # execvp(orig_argv[0], orig_argv); + > # ^ ~~~~~~~~~~~~ + > # 469| syslog(LOG_INFO, "Version mismatch, restarting"); + > # 470| sleep(1); + > # 471|-> execvp(orig_argv[0], orig_argv); + > # 472| } + > # 473| + +Signed-off-by: Victor Toso +Acked-by: Uri Lublin +--- + src/vdagent/vdagent.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index 0e2e73e..5b146db 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -418,7 +418,10 @@ int main(int argc, char *argv[]) + GOptionContext *context; + GError *error = NULL; + VDAgent *agent; +- char **orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); ++ char **orig_argv; ++ ++ orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); ++ orig_argv[argc] = NULL; + + context = g_option_context_new(NULL); + g_option_context_add_main_entries(context, entries, NULL); +-- +2.23.0 + diff --git a/0012-covscan-add-comment-on-false-positive-on-g_memdup.patch b/0012-covscan-add-comment-on-false-positive-on-g_memdup.patch new file mode 100644 index 0000000..a7e94d2 --- /dev/null +++ b/0012-covscan-add-comment-on-false-positive-on-g_memdup.patch @@ -0,0 +1,38 @@ +From 56a65ad1c6615dac97bb45865735a5a388266ffa Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Tue, 27 Aug 2019 17:15:56 +0200 +Subject: [PATCH 12/23] covscan: add comment on false-positive on g_memdup() + +Previous commit set last element of orig_argv array to NULL. +That's redundant as g_memdup() uses memcpy() and it would do +just that. Add a comment that the reason for this change is +to workaround clang's warning. + +Suggested by Uri. + +Signed-off-by: Victor Toso +Acked-by: Uri Lublin +--- + src/vdagent/vdagent.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index 5b146db..a944214 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -418,10 +418,8 @@ int main(int argc, char *argv[]) + GOptionContext *context; + GError *error = NULL; + VDAgent *agent; +- char **orig_argv; +- +- orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); +- orig_argv[argc] = NULL; ++ char **orig_argv = g_memdup(argv, sizeof(char*) * (argc+1)); ++ orig_argv[argc] = NULL; /* To avoid clang analyzer false-positive */ + + context = g_option_context_new(NULL); + g_option_context_add_main_entries(context, entries, NULL); +-- +2.23.0 + diff --git a/0013-virtio-port-handle_fds-make-read-and-write-code-cons.patch b/0013-virtio-port-handle_fds-make-read-and-write-code-cons.patch new file mode 100644 index 0000000..97cd22c --- /dev/null +++ b/0013-virtio-port-handle_fds-make-read-and-write-code-cons.patch @@ -0,0 +1,41 @@ +From f807e98bb6474949e74e1890fd483d7ef4011a6c Mon Sep 17 00:00:00 2001 +From: Uri Lublin +Date: Thu, 29 Aug 2019 19:35:24 +0300 +Subject: [PATCH 13/23] virtio-port: handle_fds: make read and write code + consistent + +A comment and curly brackets for style were added. + +Signed-off-by: Uri Lublin +Acked-by: Frediano Ziglio +--- + src/vdagentd/virtio-port.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/vdagentd/virtio-port.c b/src/vdagentd/virtio-port.c +index 3ae7f22..06f3a32 100644 +--- a/src/vdagentd/virtio-port.c ++++ b/src/vdagentd/virtio-port.c +@@ -166,14 +166,14 @@ int vdagent_virtio_port_fill_fds(struct vdagent_virtio_port *vport, + void vdagent_virtio_port_handle_fds(struct vdagent_virtio_port **vportp, + fd_set *readfds, fd_set *writefds) + { +- if (!*vportp) +- return; +- +- if (FD_ISSET((*vportp)->fd, readfds)) ++ if (*vportp && FD_ISSET((*vportp)->fd, readfds)) { + vdagent_virtio_port_do_read(vportp); ++ } + +- if (*vportp && FD_ISSET((*vportp)->fd, writefds)) ++ /* *vportp may have been destroyed in do_read */ ++ if (*vportp && FD_ISSET((*vportp)->fd, writefds)) { + vdagent_virtio_port_do_write(vportp); ++ } + } + + static struct vdagent_virtio_port_buf* vdagent_virtio_port_get_last_wbuf( +-- +2.23.0 + diff --git a/0014-Add-a-.gitpublish.patch b/0014-Add-a-.gitpublish.patch new file mode 100644 index 0000000..2079768 --- /dev/null +++ b/0014-Add-a-.gitpublish.patch @@ -0,0 +1,30 @@ +From c8f569bcbfe34c8fbb51862d69f0bb09c30542f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:36 +0100 +Subject: [PATCH 14/23] Add a .gitpublish +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Set a default profile for git-publish. +(https://github.com/stefanha/git-publish) + +Signed-off-by: Marc-André Lureau +--- + .gitpublish | 4 ++++ + 1 file changed, 4 insertions(+) + create mode 100644 .gitpublish + +diff --git a/.gitpublish b/.gitpublish +new file mode 100644 +index 0000000..71a9478 +--- /dev/null ++++ b/.gitpublish +@@ -0,0 +1,4 @@ ++[gitpublishprofile "default"] ++to = spice-devel@lists.freedesktop.org ++prefix = PATCH linux/vd-agent ++signoff = true +-- +2.23.0 + diff --git a/0015-configure-bump-gtk-3.22.patch b/0015-configure-bump-gtk-3.22.patch new file mode 100644 index 0000000..a1282af --- /dev/null +++ b/0015-configure-bump-gtk-3.22.patch @@ -0,0 +1,34 @@ +From 1d1a097ffd89c51cb82b9cec158a83b7bb5ac357 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:38 +0100 +Subject: [PATCH 15/23] configure: bump gtk+ >= 3.22 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to repology, +- Debian Stable (9): 3.22.11 +- CentOS 7: 3.22.30 +- Fedora 26: 3.22.21 (fwiw, Fedora 30: 3.24.7) + +Signed-off-by: Marc-André Lureau +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 02cf5f7..7054c17 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -82,7 +82,7 @@ AC_ARG_WITH([gtk], + [], + [with_gtk="auto"]) + if test "x$with_gtk" != "xno"; then +- PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10], [ ++ PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.22], [ + AC_DEFINE([WITH_GTK], [1], [If defined, vdagent will favor GTK+ over Xlib]) + with_gtk="yes" + ], [ +-- +2.23.0 + diff --git a/0016-clipboard-remove-vdagent-selection-id-usage.patch b/0016-clipboard-remove-vdagent-selection-id-usage.patch new file mode 100644 index 0000000..87e7983 --- /dev/null +++ b/0016-clipboard-remove-vdagent-selection-id-usage.patch @@ -0,0 +1,72 @@ +From 881869b14f48e9c5c91daf2600c52fc522fb739e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:39 +0100 +Subject: [PATCH 16/23] clipboard: remove vdagent-selection-id usage +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Modernize a bit the code, using gtk_clipboard_get_selection(). + +Signed-off-by: Marc-André Lureau +--- + src/vdagent/clipboard.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c +index a8d2e91..1e49248 100644 +--- a/src/vdagent/clipboard.c ++++ b/src/vdagent/clipboard.c +@@ -32,8 +32,26 @@ + #define SELECTION_COUNT (VD_AGENT_CLIPBOARD_SELECTION_PRIMARY + 1) + #define TYPE_COUNT (VD_AGENT_CLIPBOARD_IMAGE_JPG + 1) + +-#define sel_id_from_clip(clipboard) \ +- GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(clipboard), "vdagent-selection-id")) ++static const GdkAtom sel_atom[] = { ++ [VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD] = GDK_SELECTION_CLIPBOARD, ++ [VD_AGENT_CLIPBOARD_SELECTION_PRIMARY] = GDK_SELECTION_PRIMARY, ++}; ++ ++G_STATIC_ASSERT(G_N_ELEMENTS(sel_atom) == SELECTION_COUNT); ++ ++static gint sel_id_from_clip(GtkClipboard *clipboard) ++{ ++ GdkAtom sel = gtk_clipboard_get_selection(clipboard); ++ int i; ++ ++ for (i = 0; i < G_N_ELEMENTS(sel_atom); i++) { ++ if (sel == sel_atom[i]) { ++ return i; ++ } ++ } ++ ++ g_return_val_if_reached(0); ++} + + enum { + OWNER_NONE, +@@ -440,10 +458,6 @@ VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11 *x11, + { + #ifdef WITH_GTK + guint sel_id; +- const GdkAtom sel_atom[SELECTION_COUNT] = { +- GDK_SELECTION_CLIPBOARD, /* VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD */ +- GDK_SELECTION_PRIMARY, /* VD_AGENT_CLIPBOARD_SELECTION_PRIMARY */ +- }; + #endif + + VDAgentClipboards *c; +@@ -456,9 +470,6 @@ VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11 *x11, + for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) { + GtkClipboard *clipboard = gtk_clipboard_get(sel_atom[sel_id]); + c->selections[sel_id].clipboard = clipboard; +- /* enables the use of sel_id_from_clipboard(clipboard) macro */ +- g_object_set_data(G_OBJECT(clipboard), "vdagent-selection-id", +- GUINT_TO_POINTER(sel_id)); + g_signal_connect(G_OBJECT(clipboard), "owner-change", + G_CALLBACK(clipboard_owner_change_cb), c); + } +-- +2.23.0 + diff --git a/0017-configure-depend-on-gobject.patch b/0017-configure-depend-on-gobject.patch new file mode 100644 index 0000000..a08b614 --- /dev/null +++ b/0017-configure-depend-on-gobject.patch @@ -0,0 +1,91 @@ +From a34b3c50e78046e41520b217c6493fed66e569fa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:40 +0100 +Subject: [PATCH 17/23] configure: depend on gobject +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The following patches are going to introduce GObject. It's not a big +change, since usually glib comes installed with gobject on most systems. + +Signed-off-by: Marc-André Lureau +--- + Makefile.am | 12 ++++++------ + configure.ac | 2 +- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 3b97de5..eb39dcb 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -17,7 +17,7 @@ src_spice_vdagent_CFLAGS = \ + $(DRM_CFLAGS) \ + $(X_CFLAGS) \ + $(SPICE_CFLAGS) \ +- $(GLIB2_CFLAGS) \ ++ $(GOBJECT_CFLAGS) \ + $(GTK_CFLAGS) \ + $(ALSA_CFLAGS) \ + -I$(srcdir)/src \ +@@ -28,7 +28,7 @@ src_spice_vdagent_LDADD = \ + $(DRM_LIBS) \ + $(X_LIBS) \ + $(SPICE_LIBS) \ +- $(GLIB2_LIBS) \ ++ $(GOBJECT_LIBS) \ + $(GTK_LIBS) \ + $(ALSA_LIBS) \ + $(NULL) +@@ -52,7 +52,7 @@ src_spice_vdagent_SOURCES = \ + + tests_test_file_xfers_CFLAGS = \ + $(SPICE_CFLAGS) \ +- $(GLIB2_CFLAGS) \ ++ $(GOBJECT_CFLAGS) \ + -I$(srcdir)/src \ + -I$(srcdir)/src/vdagent \ + -DUDSCS_NO_SERVER \ +@@ -60,7 +60,7 @@ tests_test_file_xfers_CFLAGS = \ + + tests_test_file_xfers_LDADD = \ + $(SPICE_LIBS) \ +- $(GLIB2_LIBS) \ ++ $(GOBJECT_LIBS) \ + $(NULL) + + tests_test_file_xfers_SOURCES = \ +@@ -76,7 +76,7 @@ src_spice_vdagentd_CFLAGS = \ + $(LIBSYSTEMD_LOGIN_CFLAGS) \ + $(PCIACCESS_CFLAGS) \ + $(SPICE_CFLAGS) \ +- $(GLIB2_CFLAGS) \ ++ $(GOBJECT_CFLAGS) \ + $(PIE_CFLAGS) \ + -I$(srcdir)/src \ + $(NULL) +@@ -87,7 +87,7 @@ src_spice_vdagentd_LDADD = \ + $(LIBSYSTEMD_LOGIN_LIBS) \ + $(PCIACCESS_LIBS) \ + $(SPICE_LIBS) \ +- $(GLIB2_LIBS) \ ++ $(GOBJECT_LIBS) \ + $(PIE_LDFLAGS) \ + $(NULL) + +diff --git a/configure.ac b/configure.ac +index 7054c17..e77c452 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -100,7 +100,7 @@ AC_ARG_ENABLE([static-uinput], + [enable_static_uinput="$enableval"], + [enable_static_uinput="no"]) + +-PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34]) ++PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.34]) + PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11]) + PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.14.0]) + PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22]) +-- +2.23.0 + diff --git a/0018-configure-bump-gobject-2.50.patch b/0018-configure-bump-gobject-2.50.patch new file mode 100644 index 0000000..f71b0c3 --- /dev/null +++ b/0018-configure-bump-gobject-2.50.patch @@ -0,0 +1,39 @@ +From bc2e8bb21510162a8d10a5bb3a0dfc4e0034cc0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:41 +0100 +Subject: [PATCH 18/23] configure: bump gobject >= 2.50 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required for using the new GObject macros. + +According to commit 61fc548fe1a323dd2344c8ae267e3ce05e86da7d ("Bump +GLib version to 2.34"), RHEL6 is no longer supported. + +GLib version across some distributions, from repology: +- Debian Stable (9): 2.50.3 +- CentOS 7: 2.56.1 +- Fedora 26: 2.52.3 (fwiw, Fedora 30: 2.60.0) + +Signed-off-by: Marc-André Lureau +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index e77c452..a11c609 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -100,7 +100,7 @@ AC_ARG_ENABLE([static-uinput], + [enable_static_uinput="$enableval"], + [enable_static_uinput="no"]) + +-PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.34]) ++PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.50]) + PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11]) + PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.14.0]) + PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22]) +-- +2.23.0 + diff --git a/0019-vdagent-use-G_OPTION_FLAG_NONE.patch b/0019-vdagent-use-G_OPTION_FLAG_NONE.patch new file mode 100644 index 0000000..e674f5e --- /dev/null +++ b/0019-vdagent-use-G_OPTION_FLAG_NONE.patch @@ -0,0 +1,70 @@ +From be46e523c1f0e8b09bf7e409c28cf14b6e323bc0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:42 +0100 +Subject: [PATCH 19/23] vdagent: use G_OPTION_FLAG_NONE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Improve readability a bit, reindent slightly. + +Signed-off-by: Marc-André Lureau +--- + src/vdagent/vdagent.c | 37 ++++++++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 15 deletions(-) + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index a944214..e799602 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -66,25 +66,32 @@ static gchar *portdev = NULL; + static gchar *vdagentd_socket = NULL; + + static GOptionEntry entries[] = { +- { "debug", 'd', 0, +- G_OPTION_ARG_NONE, &debug, +- "Enable debug", NULL }, +- { "virtio-serial-port-path", 's', 0, ++ { "debug", 'd', ++ G_OPTION_FLAG_NONE, ++ G_OPTION_ARG_NONE, &debug, ++ "Enable debug", NULL }, ++ { "virtio-serial-port-path", 's', ++ G_OPTION_FLAG_NONE, + G_OPTION_ARG_STRING, &portdev, + "Set virtio-serial path (" DEFAULT_VIRTIO_PORT_PATH ")", NULL }, +- { "vdagentd-socket", 'S', 0, G_OPTION_ARG_STRING, +- &vdagentd_socket, +- "Set spice-vdagentd socket (" VDAGENTD_SOCKET ")", NULL }, +- { "foreground", 'x', G_OPTION_FLAG_REVERSE, +- G_OPTION_ARG_NONE, &do_daemonize, +- "Do not daemonize the agent", NULL }, +- { "file-xfer-save-dir", 'f', 0, ++ { "vdagentd-socket", 'S', ++ G_OPTION_FLAG_NONE, ++ G_OPTION_ARG_STRING, &vdagentd_socket, ++ "Set spice-vdagentd socket (" VDAGENTD_SOCKET ")", NULL }, ++ { "foreground", 'x', ++ G_OPTION_FLAG_REVERSE, ++ G_OPTION_ARG_NONE, &do_daemonize, ++ "Do not daemonize the agent", NULL }, ++ { "file-xfer-save-dir", 'f', ++ G_OPTION_FLAG_NONE, + G_OPTION_ARG_STRING, &fx_dir, + "Set directory to file transfers files", ""}, +- { "file-xfer-open-dir", 'o', 0, +- G_OPTION_ARG_INT, &fx_open_dir, +- "Open directory after completing file transfer", "<0|1>" }, +- { "x11-abort-on-error", 'y', G_OPTION_FLAG_HIDDEN, ++ { "file-xfer-open-dir", 'o', ++ G_OPTION_FLAG_NONE, ++ G_OPTION_ARG_INT, &fx_open_dir, ++ "Open directory after completing file transfer", "<0|1>" }, ++ { "x11-abort-on-error", 'y', ++ G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_NONE, &x11_sync, + "Aborts on errors from X11", NULL }, + { NULL } +-- +2.23.0 + diff --git a/0020-clipboard-gobject-ify-VDAgentClipboards.patch b/0020-clipboard-gobject-ify-VDAgentClipboards.patch new file mode 100644 index 0000000..ad25b2b --- /dev/null +++ b/0020-clipboard-gobject-ify-VDAgentClipboards.patch @@ -0,0 +1,183 @@ +From e9f6a513cf3646b76e6907575b708751c1735bb3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:43 +0100 +Subject: [PATCH 20/23] clipboard: gobject-ify VDAgentClipboards +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will allow easier lifecycle management, +and usage of gtk_clipboard_set_with_owner() + +Signed-off-by: Marc-André Lureau +--- + src/vdagent/clipboard.c | 67 +++++++++++++++++++++++++++-------------- + src/vdagent/clipboard.h | 12 +++++--- + src/vdagent/vdagent.c | 7 +++-- + 3 files changed, 56 insertions(+), 30 deletions(-) + +diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c +index 1e49248..cf6e344 100644 +--- a/src/vdagent/clipboard.c ++++ b/src/vdagent/clipboard.c +@@ -76,15 +76,25 @@ typedef struct { + } Selection; + #endif + +-struct VDAgentClipboards { +-#ifdef WITH_GTK ++struct _VDAgentClipboards { ++ GObject parent; ++ + struct udscs_connection *conn; +- Selection selections[SELECTION_COUNT]; ++ ++#ifdef WITH_GTK ++ Selection selections[SELECTION_COUNT]; + #else + struct vdagent_x11 *x11; + #endif + }; + ++struct _VDAgentClipboardsClass ++{ ++ GObjectClass parent; ++}; ++ ++G_DEFINE_TYPE(VDAgentClipboards, vdagent_clipboards, G_TYPE_OBJECT) ++ + #ifdef WITH_GTK + static const struct { + guint type; +@@ -453,43 +463,56 @@ err: + #endif + } + +-VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11 *x11, +- struct udscs_connection *conn) ++static void ++vdagent_clipboards_init(VDAgentClipboards *self) + { +-#ifdef WITH_GTK +- guint sel_id; +-#endif ++} ++ ++VDAgentClipboards *vdagent_clipboards_new(struct vdagent_x11 *x11) ++{ ++ VDAgentClipboards *self = g_object_new(VDAGENT_TYPE_CLIPBOARDS, NULL); + +- VDAgentClipboards *c; +- c = g_new0(VDAgentClipboards, 1); + #ifndef WITH_GTK +- c->x11 = x11; ++ self->x11 = x11; + #else +- c->conn = conn; ++ guint sel_id; + + for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) { + GtkClipboard *clipboard = gtk_clipboard_get(sel_atom[sel_id]); +- c->selections[sel_id].clipboard = clipboard; ++ self->selections[sel_id].clipboard = clipboard; + g_signal_connect(G_OBJECT(clipboard), "owner-change", +- G_CALLBACK(clipboard_owner_change_cb), c); ++ G_CALLBACK(clipboard_owner_change_cb), self); + } + #endif + +- return c; ++ return self; + } + +-void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive) ++void ++vdagent_clipboards_set_conn(VDAgentClipboards *self, struct udscs_connection *conn) ++{ ++ self->conn = conn; ++} ++ ++static void vdagent_clipboards_dispose(GObject *obj) + { + #ifdef WITH_GTK ++ VDAgentClipboards *self = VDAGENT_CLIPBOARDS(obj); + guint sel_id; ++ + for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) +- g_signal_handlers_disconnect_by_func(c->selections[sel_id].clipboard, +- G_CALLBACK(clipboard_owner_change_cb), c); ++ g_signal_handlers_disconnect_by_func(self->selections[sel_id].clipboard, ++ G_CALLBACK(clipboard_owner_change_cb), self); + +- if (conn_alive == FALSE) +- c->conn = NULL; +- vdagent_clipboards_release_all(c); ++ if (self->conn) ++ vdagent_clipboards_release_all(self); + #endif ++} ++ ++static void ++vdagent_clipboards_class_init(VDAgentClipboardsClass *klass) ++{ ++ GObjectClass *oclass = G_OBJECT_CLASS(klass); + +- g_free(c); ++ oclass->dispose = vdagent_clipboards_dispose; + } +diff --git a/src/vdagent/clipboard.h b/src/vdagent/clipboard.h +index f819b49..cd8eacb 100644 +--- a/src/vdagent/clipboard.h ++++ b/src/vdagent/clipboard.h +@@ -19,16 +19,18 @@ + #ifndef __VDAGENT_CLIPBOARD_H + #define __VDAGENT_CLIPBOARD_H + +-#include ++#include + + #include "x11.h" + #include "udscs.h" + +-typedef struct VDAgentClipboards VDAgentClipboards; ++#define VDAGENT_TYPE_CLIPBOARDS vdagent_clipboards_get_type() ++G_DECLARE_FINAL_TYPE(VDAgentClipboards, vdagent_clipboards, VDAGENT, CLIPBOARDS, GObject) + +-VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11 *x11, +- struct udscs_connection *conn); +-void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive); ++VDAgentClipboards *vdagent_clipboards_new(struct vdagent_x11 *x11); ++ ++void vdagent_clipboards_set_conn(VDAgentClipboards *self, ++ struct udscs_connection *conn); + + void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type); + +diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c +index e799602..db85eca 100644 +--- a/src/vdagent/vdagent.c ++++ b/src/vdagent/vdagent.c +@@ -165,8 +165,8 @@ static void vdagent_quit_loop(VDAgent *agent) + { + /* other GMainLoop(s) might be running, quit them before agent->loop */ + if (agent->clipboards) { +- vdagent_clipboards_finalize(agent->clipboards, agent->conn != NULL); +- agent->clipboards = NULL; ++ vdagent_clipboards_set_conn(agent->clipboards, agent->conn); ++ g_clear_object(&agent->clipboards); + } + if (agent->loop) + g_main_loop_quit(agent->loop); +@@ -403,7 +403,8 @@ static gboolean vdagent_init_async_cb(gpointer user_data) + if (!vdagent_init_file_xfer(agent)) + syslog(LOG_WARNING, "File transfer is disabled"); + +- agent->clipboards = vdagent_clipboards_init(agent->x11, agent->conn); ++ agent->clipboards = vdagent_clipboards_new(agent->x11); ++ vdagent_clipboards_set_conn(agent->clipboards, agent->conn); + + if (parent_socket != -1) { + if (write(parent_socket, "OK", 2) != 2) +-- +2.23.0 + diff --git a/0021-clipboard-filter-out-only-our-own-events.patch b/0021-clipboard-filter-out-only-our-own-events.patch new file mode 100644 index 0000000..57dfdc0 --- /dev/null +++ b/0021-clipboard-filter-out-only-our-own-events.patch @@ -0,0 +1,48 @@ +From 6cb59383f5179b84c7e24654728084135df63a04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:44 +0100 +Subject: [PATCH 21/23] clipboard: filter out only our own events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Do not rely on internal state when receiving clipboard events, as this +may race with external events. Use gtk_clipboard_set_with_owner() + +Signed-off-by: Marc-André Lureau +--- + src/vdagent/clipboard.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c +index cf6e344..9fb87e3 100644 +--- a/src/vdagent/clipboard.c ++++ b/src/vdagent/clipboard.c +@@ -238,8 +238,9 @@ static void clipboard_owner_change_cb(GtkClipboard *clipboard, + Selection *sel = &c->selections[sel_id]; + + /* if the event was caused by gtk_clipboard_set_with_data(), ignore it */ +- if (sel->owner == OWNER_CLIENT) ++ if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(c)) { + return; ++ } + + if (sel->owner == OWNER_GUEST) { + clipboard_new_owner(c, sel_id, OWNER_NONE); +@@ -357,9 +358,10 @@ void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id, + g_clear_pointer(&sel->last_targets_req, request_ref_cancel); + } + +- if (gtk_clipboard_set_with_data(sel->clipboard, +- targets, n_targets, +- clipboard_get_cb, clipboard_clear_cb, c)) ++ if (gtk_clipboard_set_with_owner(sel->clipboard, ++ targets, n_targets, ++ clipboard_get_cb, clipboard_clear_cb, ++ G_OBJECT(c))) + clipboard_new_owner(c, sel_id, OWNER_CLIENT); + else { + syslog(LOG_ERR, "%s: sel_id=%u: clipboard grab failed", __func__, sel_id); +-- +2.23.0 + diff --git a/0022-clipboard-only-send-release-when-no-immediate-grab.patch b/0022-clipboard-only-send-release-when-no-immediate-grab.patch new file mode 100644 index 0000000..f3595f6 --- /dev/null +++ b/0022-clipboard-only-send-release-when-no-immediate-grab.patch @@ -0,0 +1,82 @@ +From bb9c608d6a8b702c0a70be57d9ccd76eff227934 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:45 +0100 +Subject: [PATCH 22/23] clipboard: only send release when no immediate grab +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Do not send a release event between two grabs, this helps with window +manager interaction issues on peer side. + +Advertise this behaviour via a capability introduced in spice-protocol +0.12.16, so the client doesn't need to do some time-based filtering. + +(the capability shouldn't need to be negotiated, a client shouldn't +expect a release between two grabs) + +Signed-off-by: Marc-André Lureau +--- + src/vdagent/clipboard.c | 12 ++++++------ + src/vdagent/x11.c | 7 +++---- + src/vdagentd/vdagentd.c | 1 + + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c +index 9fb87e3..097c6ee 100644 +--- a/src/vdagent/clipboard.c ++++ b/src/vdagent/clipboard.c +@@ -242,13 +242,13 @@ static void clipboard_owner_change_cb(GtkClipboard *clipboard, + return; + } + +- if (sel->owner == OWNER_GUEST) { +- clipboard_new_owner(c, sel_id, OWNER_NONE); +- udscs_write(c->conn, VDAGENTD_CLIPBOARD_RELEASE, sel_id, 0, NULL, 0); +- } +- +- if (event->reason != GDK_OWNER_CHANGE_NEW_OWNER) ++ if (event->reason != GDK_OWNER_CHANGE_NEW_OWNER) { ++ if (sel->owner == OWNER_GUEST) { ++ clipboard_new_owner(c, sel_id, OWNER_NONE); ++ udscs_write(c->conn, VDAGENTD_CLIPBOARD_RELEASE, sel_id, 0, NULL, 0); ++ } + return; ++ } + + /* if there's a pending request for clipboard targets, cancel it */ + if (sel->last_targets_req) +diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c +index 6f83849..69a6142 100644 +--- a/src/vdagent/x11.c ++++ b/src/vdagent/x11.c +@@ -529,11 +529,10 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, const XEvent *even + if (ev.xfev.owner == x11->selection_window) + return; + +- /* If the clipboard owner is changed we no longer own it */ +- vdagent_x11_set_clipboard_owner(x11, selection, owner_none); +- +- if (ev.xfev.owner == None) ++ if (ev.xfev.owner == None) { ++ vdagent_x11_set_clipboard_owner(x11, selection, owner_none); + return; ++ } + + /* Request the supported targets from the new owner */ + XConvertSelection(x11->display, ev.xfev.selection, x11->targets_atom, +diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c +index 72a3e13..683e5d3 100644 +--- a/src/vdagentd/vdagentd.c ++++ b/src/vdagentd/vdagentd.c +@@ -133,6 +133,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GRAPHICS_DEVICE_INFO); ++ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB); + virtio_msg_uint32_to_le((uint8_t *)caps, size, 0); + + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, +-- +2.23.0 + diff --git a/0023-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch b/0023-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch new file mode 100644 index 0000000..c2f306c --- /dev/null +++ b/0023-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch @@ -0,0 +1,120 @@ +From d0f635b9144767e6c21d91a796b93d192de8f59e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 16:12:46 +0100 +Subject: [PATCH 23/23] clipboard: implement CAP_CLIPBOARD_GRAB_SERIAL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement the behaviour described in protocol "vdagent: introduce +VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL". + +Signed-off-by: Marc-André Lureau +--- + src/vdagentd/vdagentd.c | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c +index 683e5d3..fe98a53 100644 +--- a/src/vdagentd/vdagentd.c ++++ b/src/vdagentd/vdagentd.c +@@ -83,6 +83,7 @@ static int quit = 0; + static int retval = 0; + static int client_connected = 0; + static int max_clipboard = -1; ++static uint32_t clipboard_serial[256]; + + /* utility functions */ + static void virtio_msg_uint32_to_le(uint8_t *_msg, uint32_t size, uint32_t offset) +@@ -134,6 +135,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GRAPHICS_DEVICE_INFO); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB); ++ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL); + virtio_msg_uint32_to_le((uint8_t *)caps, size, 0); + + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, +@@ -232,6 +234,7 @@ static void do_client_capabilities(struct vdagent_virtio_port *vport, + if (debug) + syslog(LOG_DEBUG, "New client connected"); + client_connected = 1; ++ memset(clipboard_serial, 0, sizeof(clipboard_serial)); + send_capabilities(vport, 0); + } + } +@@ -241,6 +244,7 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, + { + uint32_t msg_type = 0, data_type = 0, size = message_header->size; + uint8_t selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; ++ uint32_t serial; + + if (!active_session_conn) { + syslog(LOG_WARNING, +@@ -258,6 +262,23 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, + + switch (message_header->type) { + case VD_AGENT_CLIPBOARD_GRAB: ++ if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { ++ serial = *(guint32 *)data; ++ data += 4; ++ size -= 4; ++ ++ if (serial == clipboard_serial[selection] - 1) { ++ g_debug("client grab wins"); ++ } else if (serial == clipboard_serial[selection]) { ++ clipboard_serial[selection]++; ++ } else { ++ g_debug("grab discard, serial %u != session serial %u", ++ serial, clipboard_serial[selection]); ++ return; ++ } ++ } ++ + msg_type = VDAGENTD_CLIPBOARD_GRAB; + agent_owns_clipboard[selection] = 0; + break; +@@ -480,6 +501,12 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + } + } + ++ if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL) ++ && message_header->type == VD_AGENT_CLIPBOARD_GRAB) { ++ min_size += 4; ++ } ++ + switch (message_header->type) { + case VD_AGENT_MONITORS_CONFIG: + case VD_AGENT_FILE_XFER_START: +@@ -600,6 +627,11 @@ static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, + VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + size += 4; + } ++ if (msg_type == VD_AGENT_CLIPBOARD_GRAB ++ && VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { ++ size += sizeof(uint32_t); ++ } + if (data_type != -1) { + size += 4; + } +@@ -617,8 +649,14 @@ static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, + vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4); + } + +- if (msg_type == VD_AGENT_CLIPBOARD_GRAB) ++ if (msg_type == VD_AGENT_CLIPBOARD_GRAB) { ++ if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { ++ uint32_t serial = GUINT32_TO_LE(clipboard_serial[selection]++); ++ vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&serial, sizeof(serial)); ++ } + virtio_msg_uint32_to_le(data, data_size, 0); ++ } + vdagent_virtio_port_write_append(virtio_port, data, data_size); + } + +-- +2.23.0 + diff --git a/spice-vdagent.spec b/spice-vdagent.spec index 5a167d9..00605a2 100644 --- a/spice-vdagent.spec +++ b/spice-vdagent.spec @@ -1,6 +1,6 @@ Name: spice-vdagent Version: 0.19.0 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Agent for Spice guests License: GPLv3+ URL: https://spice-space.org/ @@ -9,9 +9,43 @@ BuildRequires: systemd-devel glib2-devel spice-protocol >= 0.14.0 BuildRequires: libpciaccess-devel libXrandr-devel libXinerama-devel BuildRequires: libXfixes-devel systemd desktop-file-utils libtool BuildRequires: alsa-lib-devel dbus-devel libdrm-devel +# For autoreconf, needed after clipboard patch series +BuildRequires: automake autoconf %{?systemd_requires} Patch0001: 0001-vdagentd-Fix-session-lookup-for-new-GNOME-versions.patch +# clipboard-race patches: together with patches for spice-protocol +# and spice-gtk these fix problems interacting with mutter's new +# clipboard manager +# https://bugzilla.redhat.com/show_bug.cgi?id=1755038 +# https://patchwork.freedesktop.org/series/58418/#rev2 +# all rebased by Jakub Janků: +# https://github.com/jjanku/linux-vd_agent/tree/clipboard-race +# with several other commits needed for the clipboard fixes to apply +Patch0002: 0001-vdagent-fix-memory-leak-of-g_memdup.patch +Patch0003: 0002-x11-randr-use-glib-s-MAX-and-MIN.patch +Patch0004: 0003-x11-randr-simplest-fix-for-address-of-packed-member.patch +Patch0005: 0004-vdagent-simple-fix-for-address-of-packed-member.patch +Patch0006: 0005-x11-randr-Avoid-passing-XEvent-as-value.patch +Patch0007: 0006-x11-Avoid-passing-XEvent-as-value.patch +Patch0008: 0007-x11-Constify-XEvent-argument.patch +Patch0009: 0008-device-info-remove-g_list_length-on-compare_addresse.patch +Patch0010: 0009-x11-Change-check-to-make-code-scanners-not-giving-wa.patch +Patch0011: 0010-covscan-avoid-false-positive-on-g_clear_pointer.patch +Patch0012: 0011-covscan-initialize-argv-s-copy.patch +Patch0013: 0012-covscan-add-comment-on-false-positive-on-g_memdup.patch +Patch0014: 0013-virtio-port-handle_fds-make-read-and-write-code-cons.patch +# actual clipboard fix series starts here +Patch0015: 0014-Add-a-.gitpublish.patch +Patch0016: 0015-configure-bump-gtk-3.22.patch +Patch0017: 0016-clipboard-remove-vdagent-selection-id-usage.patch +Patch0018: 0017-configure-depend-on-gobject.patch +Patch0019: 0018-configure-bump-gobject-2.50.patch +Patch0020: 0019-vdagent-use-G_OPTION_FLAG_NONE.patch +Patch0021: 0020-clipboard-gobject-ify-VDAgentClipboards.patch +Patch0022: 0021-clipboard-filter-out-only-our-own-events.patch +Patch0023: 0022-clipboard-only-send-release-when-no-immediate-grab.patch +Patch0024: 0023-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch %description Spice agent for Linux guests offering the following features: @@ -28,7 +62,7 @@ Features: %prep %autosetup -p1 -#autoreconf -fi +autoreconf -fi %build @@ -67,6 +101,9 @@ make install DESTDIR=$RPM_BUILD_ROOT V=2 %changelog +* Fri Oct 04 2019 Adam Williamson - 0.19.0-4 +- Backport clipboard-race patches for #1755038 + * Fri Sep 13 2019 Benjamin Berg - 0.19.0-3 - Add patch to lookup graphical session https://gitlab.freedesktop.org/spice/linux/vd_agent/merge_requests/2