[gvfs] admin: Require mounting for each client explicitly



commit 8e9439ef4abf1525d8c41dc6155e6165c853cac6
Author: Ondrej Holy <oholy redhat com>
Date:   Wed Jul 12 13:36:06 2017 +0200

    admin: Require mounting for each client explicitly
    
    The admin backend is pretty special, because it can't use GMountOperation
    for authorization and polkit prompt is shown for each client. This leads
    to unwanted behavior because the admin prompt might be shown unexpectedly
    (e.g. when obtaining info for recently used files).
    
    Let's require mounting explicitly for each client. So each client gets
    G_IO_ERROR_NOT_MOUNTED if it hasn't called g_file_mountable_mount before.
    It works nicely for most of the apps which I tested (e.g. with Nautilus,
    GEdit, Totem, Evince, GIMP, LibreOffice). However, this requires changes
    for some applications, which expects that the file is already mounted
    (e.g. EOG).
    
    Unfortunatelly, it breaks utils like "gio list" because it fails with
    "The specified location is not mounted" error and "gio mount admin:///"
    doesn't help, because it has different PID.
    
    This isn't ideal, but it is better than the unexpected password prompts...
    
    https://bugzilla.gnome.org/show_bug.cgi?id=771285

 daemon/admin.mount.in     |    4 +++-
 daemon/gvfsbackendadmin.c |   22 +++++++++++++++++-----
 daemon/mount.c            |   37 ++++++++++++++++++++++++++++++++++---
 3 files changed, 54 insertions(+), 9 deletions(-)
---
diff --git a/daemon/admin.mount.in b/daemon/admin.mount.in
index cbdb164..4fb9770 100644
--- a/daemon/admin.mount.in
+++ b/daemon/admin.mount.in
@@ -2,4 +2,6 @@
 Type=admin
 # Add a dummy argument after pkexec, or '/bin/sh -c' will eat the first argument in '$@'
 Exec=/bin/sh -c 'pkexec @libexecdir@/gvfsd-admin "$@" --address $DBUS_SESSION_BUS_ADDRESS' gvfsd-admin
-AutoMount=true
+AutoMount=false
+DBusName=org.gtk.vfs.mountpoint_admin
+MountPerClient=true
diff --git a/daemon/gvfsbackendadmin.c b/daemon/gvfsbackendadmin.c
index 66c9379..d67353d 100644
--- a/daemon/gvfsbackendadmin.c
+++ b/daemon/gvfsbackendadmin.c
@@ -835,6 +835,23 @@ do_mount (GVfsBackend *backend,
   GVfsBackendAdmin *self = G_VFS_BACKEND_ADMIN (backend);
   GVfsJob *job = G_VFS_JOB (mount_job);
   GError *error = NULL;
+  GMountSpec *real_spec;
+  const gchar *client;
+
+  client = g_mount_spec_get (mount_spec, "client");
+  if (client == NULL)
+    {
+      g_vfs_job_failed_literal (job, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+                                _("Invalid mount spec"));
+      return;
+    }
+
+  g_debug ("client=%s\n", client);
+
+  real_spec = g_mount_spec_new ("admin");
+  g_mount_spec_set (real_spec, "client", client);
+  g_vfs_backend_set_mount_spec (backend, real_spec);
+  g_mount_spec_unref (real_spec);
 
   self->authority = polkit_authority_get_sync (NULL, &error);
 
@@ -880,15 +897,10 @@ static void
 g_vfs_backend_admin_init (GVfsBackendAdmin *self)
 {
   GVfsBackend *backend = G_VFS_BACKEND (self);
-  GMountSpec *mount_spec;
 
   g_mutex_init (&self->polkit_mutex);
   g_vfs_backend_set_user_visible (backend, FALSE);
 
-  mount_spec = g_mount_spec_new ("admin");
-  g_vfs_backend_set_mount_spec (backend, mount_spec);
-  g_mount_spec_unref (mount_spec);
-
   g_vfs_backend_set_icon_name (backend, "folder");
   g_vfs_backend_set_symbolic_icon_name (backend, "folder-symbolic");
 }
diff --git a/daemon/mount.c b/daemon/mount.c
index 5bab324..192923e 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -64,6 +64,7 @@ typedef struct  {
   char **scheme_aliases;
   int default_port;
   gboolean hostname_is_inet;
+  gboolean mount_per_client;
 } VfsMountable; 
 
 typedef void (*MountCallback) (VfsMountable *mountable,
@@ -535,6 +536,7 @@ read_mountable_config (void)
                            g_key_file_get_string_list (keyfile, "Mount", "SchemeAliases", NULL, NULL);
                          mountable->default_port = g_key_file_get_integer (keyfile, "Mount", "DefaultPort", 
NULL);
                          mountable->hostname_is_inet = g_key_file_get_boolean (keyfile, "Mount", 
"HostnameIsInetAddress", NULL);
+                         mountable->mount_per_client = g_key_file_get_boolean (keyfile, "Mount", 
"MountPerClient", NULL);
 
                          if (mountable->scheme == NULL)
                            mountable->scheme = g_strdup (mountable->type);
@@ -774,6 +776,20 @@ lookup_mount (GVfsDBusMountTracker *object,
                                                    vfs_mount_to_dbus (mount)); 
 }
 
+static void
+sanitize_spec (GMountSpec *spec, GDBusMethodInvocation *invocation)
+{
+  const gchar *client;
+  VfsMountable *mountable;
+
+  mountable = lookup_mountable (spec);
+  if (mountable && mountable->mount_per_client)
+    {
+      client = g_dbus_method_invocation_get_sender (invocation);
+      g_mount_spec_set (spec, "client", client);
+    }
+}
+
 static gboolean 
 handle_lookup_mount (GVfsDBusMountTracker *object,
                      GDBusMethodInvocation *invocation,
@@ -786,6 +802,7 @@ handle_lookup_mount (GVfsDBusMountTracker *object,
 
   if (spec != NULL)
     {
+      sanitize_spec (spec, invocation);
       lookup_mount (object, invocation, spec, TRUE);
       g_mount_spec_unref (spec);
     }
@@ -822,16 +839,28 @@ handle_lookup_mount_by_fuse_path (GVfsDBusMountTracker *object,
 
 static void
 build_mounts_array (GVariantBuilder *mounts_array,
-                    gboolean user_visible_only)
+                    gboolean user_visible_only,
+                    GDBusMethodInvocation *invocation)
 {
   GList *l;
   VfsMount *mount;
+  VfsMountable *mountable;
 
   g_variant_builder_init (mounts_array, G_VARIANT_TYPE (VFS_MOUNT_ARRAY_DBUS_STRUCT_TYPE));
   for (l = mounts; l != NULL; l = l->next)
     {
       mount = l->data;
 
+      mountable = lookup_mountable (mount->mount_spec);
+      if (mountable && mountable->mount_per_client)
+        {
+          const gchar *client;
+
+          client = g_dbus_method_invocation_get_sender (invocation);
+          if (g_strcmp0 (g_mount_spec_get (mount->mount_spec, "client"), client) != 0)
+            continue;
+        }
+
       if (!user_visible_only || mount->user_visible)
         g_variant_builder_add_value (mounts_array, vfs_mount_to_dbus (mount));
     }
@@ -844,7 +873,7 @@ handle_list_mounts (GVfsDBusMountTracker *object,
 {
   GVariantBuilder mounts_array;
 
-  build_mounts_array (&mounts_array, FALSE);
+  build_mounts_array (&mounts_array, FALSE, invocation);
 
   gvfs_dbus_mount_tracker_complete_list_mounts (object, invocation,
                                                 g_variant_builder_end (&mounts_array));
@@ -860,7 +889,7 @@ handle_list_mounts2 (GVfsDBusMountTracker *object,
 {
   GVariantBuilder mounts_array;
 
-  build_mounts_array (&mounts_array, arg_user_visible_only);
+  build_mounts_array (&mounts_array, arg_user_visible_only, invocation);
 
   gvfs_dbus_mount_tracker_complete_list_mounts2 (object, invocation,
                                                  g_variant_builder_end (&mounts_array));
@@ -903,6 +932,8 @@ handle_mount_location (GVfsDBusMountTracker *object,
   else
     {
       VfsMount *mount;
+
+      sanitize_spec (spec, invocation);
       mount = match_vfs_mount (spec);
       
       if (mount != NULL)


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