[glib/sandboxed-dbus-activation] Make dbus activation sandbox-aware
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/sandboxed-dbus-activation] Make dbus activation sandbox-aware
- Date: Sat, 6 May 2017 18:25:34 +0000 (UTC)
commit 4b21c4ea23c4643f91013fb8495466dcfe992270
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. 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 | 148 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 144 insertions(+), 4 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 81dff27..940c8ac 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,6 +2836,131 @@ g_desktop_app_info_make_platform_data (GDesktopAppInfo *info,
return g_variant_builder_end (&builder);
}
+#ifdef G_OS_UNIX
+static GList *
+rewrite_uris_for_portal (GDesktopAppInfo *info,
+ GDBusConnection *session_bus,
+ GList *uris)
+{
+ GVariantBuilder builder;
+ GUnixFDList *fd_list = NULL;
+ int *map = NULL;
+ int i, j;
+ GVariant *ret1 = NULL;
+ GVariant *ret2 = NULL;
+ GList *result = NULL;
+ char *mountpoint;
+ char **doc_ids;
+ GList *l;
+ GError *error = NULL;
+
+ ret1 = g_dbus_connection_call_sync (session_bus,
+ "org.freedesktop.portal.Documents",
+ "/org/freedesktop/portal/documents",
+ "org.freedesktop.portal.Documents",
+ "GetMountPoint",
+ NULL,
+ G_VARIANT_TYPE ("(ay)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (ret1 == NULL)
+ {
+ g_warning ("Failed to get mountpoint: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add (&builder, "s", info->app_id);
+
+ map = g_new (int, g_list_length (uris));
+ fd_list = g_unix_fd_list_new ();
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("ah"));
+ for (l = uris, i = 0, j = 0; l; l = l->next, i++)
+ {
+ const char *uri = l->data;
+
+ map[i] = -1;
+
+ if (g_str_has_prefix (uri, "file:"))
+ {
+ const char *path;
+ int fd;
+ int idx;
+
+ path = uri + strlen ("file:");
+
+ fd = open (path, O_CLOEXEC | O_PATH);
+ if (fd < 0)
+ continue;
+
+ idx = g_unix_fd_list_append (fd_list, fd, NULL);
+ if (idx == -1)
+ continue;
+
+ g_variant_builder_add (&builder, "h", idx);
+ map[i] = j++;
+ }
+ }
+ g_variant_builder_close (&builder);
+
+ ret2 = g_dbus_connection_call_with_unix_fd_list_sync (session_bus,
+ "org.freedesktop.portal.Documents",
+ "/org/freedesktop/portal/documents",
+ "org.freedesktop.portal.Documents",
+ "AddMany",
+ g_variant_builder_end (&builder),
+ G_VARIANT_TYPE ("(as)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ fd_list,
+ NULL,
+ NULL,
+ &error);
+ if (ret2 == NULL)
+ {
+ g_warning ("Failed to add many! %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_variant_get (ret1, "(^&ay)", &mountpoint),
+ g_variant_get (ret2, "(^a&s)", &doc_ids);
+
+ for (l = uris, i = 0; l; l = l->next, i++)
+ {
+ char *uri = l->data;
+ char *ruri;
+
+ if (map[i] == -1)
+ ruri = g_strdup (uri);
+ else if (strcmp (doc_ids[map[i]], "") == 0)
+ ruri = g_strdup (uri);
+ else
+ {
+ char *basename = g_path_get_basename (uri + strlen ("file:"));
+ char *doc_path = g_build_filename (mountpoint, doc_ids[map[i]], basename, NULL);
+ ruri = g_strconcat ("file:", doc_path, NULL);
+ g_free (basename);
+ g_free (doc_path);
+ }
+
+ result = g_list_append (result, ruri);
+ }
+
+out:
+ g_free (map);
+ g_clear_object (&fd_list);
+ g_clear_pointer (&ret1, g_variant_unref);
+ g_clear_pointer (&ret2, g_variant_unref);
+
+ return result;
+}
+#endif
+
static gboolean
g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo *info,
GDBusConnection *session_bus,
@@ -2843,22 +2969,29 @@ g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo *info,
{
GVariantBuilder builder;
gchar *object_path;
+ GList *ruris;
g_return_val_if_fail (info != NULL, FALSE);
+#ifdef G_OS_UNIX
+ ruris = rewrite_uris_for_portal (info, session_bus, uris);
+#else
+ ruris = uris;
+#endif
+
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
- if (uris)
+ if (ruris)
{
GList *iter;
g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY);
- for (iter = uris; iter; iter = iter->next)
+ for (iter = ruris; iter; iter = iter->next)
g_variant_builder_add (&builder, "s", iter->data);
g_variant_builder_close (&builder);
}
- g_variant_builder_add_value (&builder, g_desktop_app_info_make_platform_data (info, uris, launch_context));
+ g_variant_builder_add_value (&builder, g_desktop_app_info_make_platform_data (info, ruris,
launch_context));
/* This is non-blocking API. Similar to launching via fork()/exec()
* we don't wait around to see if the program crashed during startup.
@@ -2866,9 +2999,15 @@ g_desktop_app_info_launch_uris_with_dbus (GDesktopAppInfo *info,
*/
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),
+ ruris ? "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
+ g_list_free_full (ruris, g_free);
+#endif
return TRUE;
}
@@ -2890,6 +3029,7 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo,
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+g_print ("launch uris: bus %d, app id %s\n", session_bus != NULL, info->app_id);
if (session_bus && info->app_id)
g_desktop_app_info_launch_uris_with_dbus (info, session_bus, uris, launch_context);
else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]