[glib/sandboxed-dbus-activation] Make dbus activation sandbox-aware



commit d4e6eae516a5c1968d66b9965e01bf1e702a6393
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 6 14:22:38 2017 -0400

    Make dbus activation sandbox-aware
    
    When we call org.freedesktop.Application.Open to activate
    an application and pass file uris, the application may not
    be able to see the files due to a flatpak sandbox. Flatpak
    puts an X-Flatpak marker in desktop files that it exports,
    so we can easily recognize applications that may be affected
    by this. In this case, call the document portal to export
    the files and pass the resulting uri's instead of the original
    ones.

 gio/gdesktopappinfo.c |  180 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 173 insertions(+), 7 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 81dff27..0f0b256 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -36,6 +36,7 @@
 #include "gdesktopappinfo.h"
 #ifdef G_OS_UNIX
 #include "glib-unix.h"
+#include "gunixfdlist.h"
 #endif
 #include "gfile.h"
 #include "gioerror.h"
@@ -2835,17 +2836,15 @@ g_desktop_app_info_make_platform_data (GDesktopAppInfo   *info,
   return g_variant_builder_end (&builder);
 }
 
-static gboolean
-g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo    *info,
-                                          GDBusConnection    *session_bus,
-                                          GList              *uris,
-                                          GAppLaunchContext  *launch_context)
+static void
+launch_uris_with_dbus (GDesktopAppInfo    *info,
+                       GDBusConnection    *session_bus,
+                       GList              *uris,
+                       GAppLaunchContext  *launch_context)
 {
   GVariantBuilder builder;
   gchar *object_path;
 
-  g_return_val_if_fail (info != NULL, FALSE);
-
   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
 
   if (uris)
@@ -2865,10 +2864,177 @@ g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo    *info,
    * This is what startup-notification's job is...
    */
   object_path = object_path_from_appid (info->app_id);
+
   g_dbus_connection_call (session_bus, info->app_id, object_path, "org.freedesktop.Application",
                           uris ? "Open" : "Activate", g_variant_builder_end (&builder),
                           NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+
   g_free (object_path);
+}
+
+#ifdef G_OS_UNIX
+typedef struct {
+  GDesktopAppInfo *info;
+  GAppLaunchContext *context;
+  GList *uris;
+  gboolean *as_is;
+} LaunchData;
+
+static void
+free_launch_data (LaunchData *data)
+{
+  g_object_unref (data->info);
+  g_object_unref (data->context);
+  g_list_free_full (data->uris, g_free);
+  g_free (data->as_is);
+  g_free (data);
+}
+
+static void
+rewrite_uris_done (GObject      *source,
+                   GAsyncResult *res,
+                   gpointer      data)
+{
+  GDBusConnection *session_bus = G_DBUS_CONNECTION (source);
+  LaunchData *ld = data;
+  g_autoptr(GVariant) ret = NULL;
+  g_autoptr(GError) error = NULL;
+  char *mountpoint;
+  char **doc_ids;
+  GList *l;
+  GList *ruris;
+  int i, j;
+
+  ret = g_dbus_connection_call_with_unix_fd_list_finish (session_bus, NULL, res, &error);
+  if (ret == NULL)
+    {
+      g_warning ("Failed to call AddMany: %s", error->message);
+      launch_uris_with_dbus (ld->info, session_bus, ld->uris, ld->context);
+      free_launch_data (ld);
+      return;
+    }
+
+  g_variant_get (ret, "(^a&s^&ay)", &doc_ids, &mountpoint);
+
+  ruris = NULL;
+
+  for (l = ld->uris, i = 0, j = 0; l; l = l->next, i++)
+    {
+      char *uri = l->data;
+      char *ruri;
+
+      if (ld->as_is[i])
+        ruri = g_strdup (uri);
+      else if (strcmp (doc_ids[j], "") == 0) /* use as-is */
+        {
+          ruri = g_strdup (uri);
+          j++;
+        }
+      else
+        {
+           char *basename = g_path_get_basename (uri + strlen ("file:"));
+           char *doc_path = g_build_filename (mountpoint, doc_ids[j], basename, NULL);
+           ruri = g_strconcat ("file:", doc_path, NULL);
+           g_free (basename);
+           g_free (doc_path);
+           j++;
+        }
+
+      ruris = g_list_append (ruris, ruri);
+    }
+
+  launch_uris_with_dbus (ld->info, session_bus, ruris, ld->context);
+  free_launch_data (ld);
+  g_list_free_full (ruris, g_free);
+}
+
+static void
+rewrite_uris_for_portal (GDesktopAppInfo   *info,
+                         GDBusConnection   *session_bus,
+                         GList             *uris,
+                         GAppLaunchContext *context)
+{
+  GVariantBuilder builder;
+  GUnixFDList *fd_list = NULL;
+  GList *l;
+  int i;
+  LaunchData *data;
+
+  data = g_new (LaunchData, 1);
+  data->info = g_object_ref (info);
+  data->context = g_object_ref (context);
+  data->uris = g_list_copy_deep (uris, (GCopyFunc)g_strdup, NULL);
+  data->as_is = g_new (gboolean, g_list_length (uris));
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
+  g_variant_builder_add (&builder, "s", info->app_id);
+  g_variant_builder_open (&builder, G_VARIANT_TYPE ("ah"));
+
+  fd_list = g_unix_fd_list_new ();
+  for (l = uris, i = 0; l; l = l->next, i++)
+    {
+      const char *uri = l->data;
+      int idx = -1;
+
+      if (g_str_has_prefix (uri, "file:"))
+        {
+          const char *path;
+          int fd;
+
+          path = uri + strlen ("file:");
+
+          fd = open (path, O_CLOEXEC | O_PATH);
+          if (fd >= 0)
+            {
+              idx = g_unix_fd_list_append (fd_list, fd, NULL);
+              close (fd);
+            }
+        }
+
+      data->as_is[i] = idx != -1;
+      if (idx != -1)
+        g_variant_builder_add (&builder, "h", idx);
+    }
+
+  g_variant_builder_close (&builder);
+
+  g_dbus_connection_call_with_unix_fd_list (session_bus,
+                                            "org.freedesktop.portal.Documents",
+                                            "/org/freedesktop/portal/documents",
+                                            "org.freedesktop.portal.Documents",
+                                            "AddMany",
+                                            g_variant_builder_end (&builder),
+                                            G_VARIANT_TYPE ("(asay)"),
+                                            G_DBUS_CALL_FLAGS_NONE,
+                                            -1,
+                                            fd_list,
+                                            NULL,
+                                            rewrite_uris_done,
+                                            data);
+  g_object_unref (fd_list);
+}
+
+static gboolean
+should_rewrite_uris_for_portal (GDesktopAppInfo *info)
+{
+  return g_desktop_app_info_get_boolean (info, "X-Flatpak");
+}
+#endif
+
+static gboolean
+g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo    *info,
+                                          GDBusConnection    *session_bus,
+                                          GList              *uris,
+                                          GAppLaunchContext  *launch_context)
+{
+  g_return_val_if_fail (info != NULL, FALSE);
+
+#ifdef G_OS_UNIX
+  if (should_rewrite_uris_for_portal (info))
+    rewrite_uris_for_portal (info, session_bus, uris, launch_context);
+  else
+#endif
+    launch_uris_with_dbus (info, session_bus, uris, launch_context);
 
   return TRUE;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]