[Spice-devel] [PATCH spice-gtk 1/5] Block sending clipboard data > max-clipboard

Marc-André Lureau marcandre.lureau at gmail.com
Wed Nov 6 13:25:08 PST 2013


From: Marc-André Lureau <marcandre.lureau at redhat.com>

Attempt to send very large clipboard data may easy cause OOM
abort, either in  gdk - some patch are proposed to improve the situation,
or in spice-gtk itself.

Let's have a property that blocks unreasonably big clipboard data from
being processed (by default 100mb). Users willing to send larger data
can use the send basic drag-drop send file instead, or tweak the
property value.
---
 gtk/channel-main.c      | 28 ++++++++++++++++++++++++++++
 gtk/spice-gtk-session.c |  9 ++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 5c33e67..dbcaff8 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -106,6 +106,7 @@ struct _SpiceMainChannelPrivate  {
     guint                       switch_host_delayed_id;
     guint                       migrate_delayed_id;
     spice_migrate               *migrate_data;
+    int                         max_clipboard;
 };
 
 struct spice_migrate {
@@ -137,6 +138,7 @@ enum {
     PROP_DISPLAY_COLOR_DEPTH,
     PROP_DISABLE_DISPLAY_POSITION,
     PROP_DISABLE_DISPLAY_ALIGN,
+    PROP_MAX_CLIPBOARD,
 };
 
 /* Signals */
@@ -253,6 +255,9 @@ static void spice_main_get_property(GObject    *object,
     case PROP_DISABLE_DISPLAY_ALIGN:
         g_value_set_boolean(value, c->disable_display_align);
         break;
+    case PROP_MAX_CLIPBOARD:
+        g_value_set_int(value, c->max_clipboard);
+        break;
     default:
 	G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 	break;
@@ -286,6 +291,9 @@ static void spice_main_set_property(GObject *gobject, guint prop_id,
     case PROP_DISABLE_DISPLAY_ALIGN:
         c->disable_display_align = g_value_get_boolean(value);
         break;
+    case PROP_MAX_CLIPBOARD:
+        c->max_clipboard = g_value_get_int(value);
+        break;
     default:
 	G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
 	break;
@@ -512,6 +520,24 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
                               G_PARAM_CONSTRUCT |
                               G_PARAM_STATIC_STRINGS));
 
+    /**
+     * SpiceMainChannel:max-clipboard:
+     *
+     * Maximum size of clipboard operations in bytes (default 100MB,
+     * -1 for unlimited size);
+     *
+     * Since: 0.22
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_MAX_CLIPBOARD,
+         g_param_spec_int("max-clipboard",
+                          "max clipboard",
+                          "Maximum clipboard data size",
+                          -1, G_MAXINT, 100 * 1024 * 1024,
+                          G_PARAM_READWRITE |
+                          G_PARAM_CONSTRUCT |
+                          G_PARAM_STATIC_STRINGS));
+
     /* TODO use notify instead */
     /**
      * SpiceMainChannel::main-mouse-update:
@@ -1246,6 +1272,8 @@ static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
     g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
         G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
 
+    g_return_if_fail(c->max_clipboard == -1 || size < c->max_clipboard);
+
     msgsize = sizeof(VDAgentClipboard);
     if (HAS_CLIPBOARD_SELECTION(c))
         msgsize += 4;
diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 71ed300..eab7e2f 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -748,16 +748,19 @@ static void clipboard_received_cb(GtkClipboard *clipboard,
     gchar* name;
     GdkAtom atom;
     int selection;
+    int max_clipboard;
 
     selection = get_selection_from_clipboard(s, clipboard);
     g_return_if_fail(selection != -1);
 
+    g_object_get(s->main, "max-clipboard", &max_clipboard, NULL);
     len = gtk_selection_data_get_length(selection_data);
-    if (len == -1) {
+    if (len == 0 || (max_clipboard != -1 && len > max_clipboard)) {
+        g_warning("discarded clipboard of size %d (max: %d)", len, max_clipboard);
+        return;
+    } else if (len == -1) {
         SPICE_DEBUG("empty clipboard");
         len = 0;
-    } else if (len == 0) {
-        SPICE_DEBUG("TODO: what should be done here?");
     } else {
         atom = gtk_selection_data_get_data_type(selection_data);
         name = gdk_atom_name(atom);
-- 
1.8.3.1



More information about the Spice-devel mailing list