import gvfs-1.36.2-16.el8

c8-beta imports/c8-beta/gvfs-1.36.2-16.el8
MSVSphere Packaging Team 9 months ago
commit a0571b75d8

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/gvfs-1.36.2.tar.xz

@ -0,0 +1 @@
fb5fe05f0661da8c88f5fa41014bcd526ad39993 SOURCES/gvfs-1.36.2.tar.xz

@ -0,0 +1,127 @@
From 5cd76d627f4d1982b6e77a0e271ef9301732d09e Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Thu, 23 May 2019 10:24:36 +0200
Subject: [PATCH] admin: Add query_info_on_read/write functionality
Admin backend doesn't implement query_info_on_read/write which might
potentially lead to some race conditions which aren't really wanted
especially in case of admin backend. Let's add this missing functionality.
---
daemon/gvfsbackendadmin.c | 79 +++++++++++++++++++++++++++++++++------
1 file changed, 67 insertions(+), 12 deletions(-)
diff --git a/daemon/gvfsbackendadmin.c b/daemon/gvfsbackendadmin.c
index 65a979e7..23d16f16 100644
--- a/daemon/gvfsbackendadmin.c
+++ b/daemon/gvfsbackendadmin.c
@@ -42,6 +42,8 @@
#include "gvfsjobopenforwrite.h"
#include "gvfsjobqueryattributes.h"
#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryinforead.h"
+#include "gvfsjobqueryinfowrite.h"
#include "gvfsjobread.h"
#include "gvfsjobseekread.h"
#include "gvfsjobseekwrite.h"
@@ -155,6 +157,19 @@ complete_job (GVfsJob *job,
g_vfs_job_succeeded (job);
}
+static void
+fix_file_info (GFileInfo *info)
+{
+ /* Override read/write flags, since the above call will use access()
+ * to determine permissions, which does not honor our privileged
+ * capabilities.
+ */
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, TRUE);
+}
+
static void
do_query_info (GVfsBackend *backend,
GVfsJobQueryInfo *query_info_job,
@@ -180,19 +195,57 @@ do_query_info (GVfsBackend *backend,
if (error != NULL)
goto out;
- /* Override read/write flags, since the above call will use access()
- * to determine permissions, which does not honor our privileged
- * capabilities.
- */
- g_file_info_set_attribute_boolean (real_info,
- G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
- g_file_info_set_attribute_boolean (real_info,
- G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
- g_file_info_set_attribute_boolean (real_info,
- G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
- g_file_info_set_attribute_boolean (real_info,
- G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, TRUE);
+ fix_file_info (real_info);
+ g_file_info_copy_into (real_info, info);
+ g_object_unref (real_info);
+
+ out:
+ complete_job (job, error);
+}
+
+static void
+do_query_info_on_read (GVfsBackend *backend,
+ GVfsJobQueryInfoRead *query_info_job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsJob *job = G_VFS_JOB (query_info_job);
+ GFileInputStream *stream = handle;
+ GError *error = NULL;
+ GFileInfo *real_info;
+
+ real_info = g_file_input_stream_query_info (stream, query_info_job->attributes,
+ job->cancellable, &error);
+ if (error != NULL)
+ goto out;
+
+ fix_file_info (real_info);
+ g_file_info_copy_into (real_info, info);
+ g_object_unref (real_info);
+
+ out:
+ complete_job (job, error);
+}
+
+static void
+do_query_info_on_write (GVfsBackend *backend,
+ GVfsJobQueryInfoWrite *query_info_job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsJob *job = G_VFS_JOB (query_info_job);
+ GFileOutputStream *stream = handle;
+ GError *error = NULL;
+ GFileInfo *real_info;
+
+ real_info = g_file_output_stream_query_info (stream, query_info_job->attributes,
+ job->cancellable, &error);
+ if (error != NULL)
+ goto out;
+ fix_file_info (real_info);
g_file_info_copy_into (real_info, info);
g_object_unref (real_info);
@@ -868,6 +921,8 @@ g_vfs_backend_admin_class_init (GVfsBackendAdminClass * klass)
backend_class->mount = do_mount;
backend_class->open_for_read = do_open_for_read;
backend_class->query_info = do_query_info;
+ backend_class->query_info_on_read = do_query_info_on_read;
+ backend_class->query_info_on_write = do_query_info_on_write;
backend_class->read = do_read;
backend_class->create = do_create;
backend_class->append_to = do_append_to;
--
2.23.0

@ -0,0 +1,80 @@
From d5dfd823c94045488aef8727c553f1e0f7666b90 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Fri, 24 May 2019 09:43:43 +0200
Subject: [PATCH] admin: Ensure correct ownership when moving to file:// uri
User and group is not restored properly when moving (or copying with
G_FILE_COPY_ALL_METADATA) from admin:// to file://, because it is handled
by GIO fallback code, which doesn't run with root permissions. Let's
handle this case with pull method to ensure correct ownership.
---
daemon/gvfsbackendadmin.c | 46 +++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/daemon/gvfsbackendadmin.c b/daemon/gvfsbackendadmin.c
index 32b51b1a..9a7e8295 100644
--- a/daemon/gvfsbackendadmin.c
+++ b/daemon/gvfsbackendadmin.c
@@ -807,6 +807,51 @@ do_move (GVfsBackend *backend,
complete_job (job, error);
}
+static void
+do_pull (GVfsBackend *backend,
+ GVfsJobPull *pull_job,
+ const char *source,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendAdmin *self = G_VFS_BACKEND_ADMIN (backend);
+ GVfsJob *job = G_VFS_JOB (pull_job);
+ GError *error = NULL;
+ GFile *src_file, *dst_file;
+
+ /* Pull method is necessary when user/group needs to be restored, return
+ * G_IO_ERROR_NOT_SUPPORTED in other cases to proceed with the fallback code.
+ */
+ if (!(flags & G_FILE_COPY_ALL_METADATA))
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported"));
+ return;
+ }
+
+ if (!check_permission (self, job))
+ return;
+
+ src_file = g_file_new_for_path (source);
+ dst_file = g_file_new_for_path (local_path);
+
+ if (remove_source)
+ g_file_move (src_file, dst_file, flags, job->cancellable,
+ progress_callback, progress_callback_data, &error);
+ else
+ g_file_copy (src_file, dst_file, flags, job->cancellable,
+ progress_callback, progress_callback_data, &error);
+
+ g_object_unref (src_file);
+ g_object_unref (dst_file);
+
+ complete_job (job, error);
+}
+
static void
do_query_settable_attributes (GVfsBackend *backend,
GVfsJobQueryAttributes *query_job,
@@ -927,6 +972,7 @@ g_vfs_backend_admin_class_init (GVfsBackendAdminClass * klass)
backend_class->set_attribute = do_set_attribute;
backend_class->delete = do_delete;
backend_class->move = do_move;
+ backend_class->pull = do_pull;
backend_class->query_settable_attributes = do_query_settable_attributes;
backend_class->query_writable_namespaces = do_query_writable_namespaces;
}
--
2.23.0

@ -0,0 +1,42 @@
From d8d0c8c40049cfd824b2b90d0cd47914052b9811 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Wed, 2 Jan 2019 17:13:27 +0100
Subject: [PATCH] admin: Prevent access if any authentication agent isn't
available
The backend currently allows to access and modify files without prompting
for password if any polkit authentication agent isn't available. This seems
isn't usually problem, because polkit agents are integral parts of
graphical environments / linux distributions. The agents can't be simply
disabled without root permissions and are automatically respawned. However,
this might be a problem in some non-standard cases.
This affects only users which belong to wheel group (i.e. those who are
already allowed to use sudo). It doesn't allow privilege escalation for
users, who don't belong to that group.
Let's return permission denied error also when the subject can't be
authorized by any polkit agent to prevent this behavior.
Closes: https://gitlab.gnome.org/GNOME/gvfs/issues/355
---
daemon/gvfsbackendadmin.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/daemon/gvfsbackendadmin.c b/daemon/gvfsbackendadmin.c
index ec0f2392..0f849008 100644
--- a/daemon/gvfsbackendadmin.c
+++ b/daemon/gvfsbackendadmin.c
@@ -130,8 +130,7 @@ check_permission (GVfsBackendAdmin *self,
return FALSE;
}
- is_authorized = polkit_authorization_result_get_is_authorized (result) ||
- polkit_authorization_result_get_is_challenge (result);
+ is_authorized = polkit_authorization_result_get_is_authorized (result);
g_object_unref (result);
--
2.20.1

@ -0,0 +1,87 @@
From d7d362995aa0cb8905c8d5c2a2a4c305d2ffff80 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Thu, 23 May 2019 10:33:30 +0200
Subject: [PATCH] admin: Use fsuid to ensure correct file ownership
Files created over admin backend should be owned by root, but they are
owned by the user itself. This is because the daemon drops the uid to
make dbus connection work. Use fsuid and euid to fix this issue.
Closes: https://gitlab.gnome.org/GNOME/gvfs/issues/21
---
daemon/gvfsbackendadmin.c | 29 +++++++----------------------
1 file changed, 7 insertions(+), 22 deletions(-)
diff --git a/daemon/gvfsbackendadmin.c b/daemon/gvfsbackendadmin.c
index a74d09cf..32b51b1a 100644
--- a/daemon/gvfsbackendadmin.c
+++ b/daemon/gvfsbackendadmin.c
@@ -157,19 +157,6 @@ complete_job (GVfsJob *job,
g_vfs_job_succeeded (job);
}
-static void
-fix_file_info (GFileInfo *info)
-{
- /* Override read/write flags, since the above call will use access()
- * to determine permissions, which does not honor our privileged
- * capabilities.
- */
- g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
- g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
- g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
- g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, TRUE);
-}
-
static void
do_query_info (GVfsBackend *backend,
GVfsJobQueryInfo *query_info_job,
@@ -195,7 +182,6 @@ do_query_info (GVfsBackend *backend,
if (error != NULL)
goto out;
- fix_file_info (real_info);
g_file_info_copy_into (real_info, info);
g_object_unref (real_info);
@@ -220,7 +206,6 @@ do_query_info_on_read (GVfsBackend *backend,
if (error != NULL)
goto out;
- fix_file_info (real_info);
g_file_info_copy_into (real_info, info);
g_object_unref (real_info);
@@ -245,7 +230,6 @@ do_query_info_on_write (GVfsBackend *backend,
if (error != NULL)
goto out;
- fix_file_info (real_info);
g_file_info_copy_into (real_info, info);
g_object_unref (real_info);
@@ -977,14 +961,15 @@ acquire_caps (uid_t uid)
struct __user_cap_header_struct hdr;
struct __user_cap_data_struct data;
- /* Tell kernel not clear capabilities when dropping root */
- if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
- g_error ("prctl(PR_SET_KEEPCAPS) failed");
-
- /* Drop root uid, but retain the required permitted caps */
- if (setuid (uid) < 0)
+ /* Set euid to user to make dbus work */
+ if (seteuid (uid) < 0)
g_error ("unable to drop privs");
+ /* Set fsuid to still behave like root when working with files */
+ setfsuid (0);
+ if (setfsuid (-1) != 0)
+ g_error ("setfsuid failed");
+
memset (&hdr, 0, sizeof(hdr));
hdr.version = _LINUX_CAPABILITY_VERSION;
--
2.23.0

@ -0,0 +1,385 @@
From af4d0d88604af7c196e461a743f2d1e81239d76a Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Tue, 14 May 2019 09:31:37 +0200
Subject: [PATCH 2/3] daemon: Handle lockdown option to disable writing
Handle the new mount-removable-storage-devices-as-read-only option of
org.gnome.desktop.lockdown schema and present AFC, MTP, GPhoto2 devices
as read-only if enabled.
---
daemon/gvfsbackend.c | 62 ++++++++++++++++++++++++++++++++--
daemon/gvfsbackend.h | 6 ++++
daemon/gvfsbackendafc.c | 2 ++
daemon/gvfsbackendgphoto2.c | 1 +
daemon/gvfsbackendmtp.c | 1 +
daemon/gvfsjobcopy.c | 7 ++++
daemon/gvfsjobdelete.c | 7 ++++
daemon/gvfsjobmakedirectory.c | 7 ++++
daemon/gvfsjobmakesymlink.c | 7 ++++
daemon/gvfsjobmove.c | 7 ++++
daemon/gvfsjobopenforwrite.c | 7 ++++
daemon/gvfsjobpush.c | 7 ++++
daemon/gvfsjobqueryfsinfo.c | 11 ++----
daemon/gvfsjobsetattribute.c | 7 ++++
daemon/gvfsjobsetdisplayname.c | 7 ++++
daemon/gvfsjobtrash.c | 7 ++++
16 files changed, 143 insertions(+), 10 deletions(-)
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index 4fd3455c..599733ef 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -80,6 +80,9 @@ struct _GVfsBackendPrivate
char *default_location;
GMountSpec *mount_spec;
gboolean block_requests;
+
+ GSettings *lockdown_settings;
+ gboolean readonly_lockdown;
};
@@ -155,7 +158,9 @@ g_vfs_backend_finalize (GObject *object)
g_free (backend->priv->default_location);
if (backend->priv->mount_spec)
g_mount_spec_unref (backend->priv->mount_spec);
-
+
+ g_clear_object (&backend->priv->lockdown_settings);
+
if (G_OBJECT_CLASS (g_vfs_backend_parent_class)->finalize)
(*G_OBJECT_CLASS (g_vfs_backend_parent_class)->finalize) (object);
}
@@ -587,7 +592,29 @@ g_vfs_backend_add_auto_info (GVfsBackend *backend,
g_file_attribute_matcher_matches (matcher,
G_FILE_ATTRIBUTE_THUMBNAILING_FAILED)))
get_thumbnail_attributes (uri, info);
-
+
+ if (backend->priv->readonly_lockdown)
+ {
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ }
+}
+
+void
+g_vfs_backend_add_auto_fs_info (GVfsBackend *backend,
+ GFileAttributeMatcher *matcher,
+ GFileInfo *info)
+{
+ const char *type;
+
+ type = g_vfs_backend_get_backend_type (backend);
+ if (type)
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_GVFS_BACKEND, type);
+
+ if (backend->priv->readonly_lockdown)
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
}
void
@@ -1047,3 +1074,34 @@ g_vfs_backend_force_unmount (GVfsBackend *backend)
(GAsyncReadyCallback) forced_unregister_mount_callback,
NULL);
}
+
+static void
+lockdown_settings_changed (GSettings *settings,
+ gchar *key,
+ gpointer user_data)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (user_data);
+
+ backend->priv->readonly_lockdown = g_settings_get_boolean (settings,
+ "mount-removable-storage-devices-as-read-only");
+}
+
+
+void
+g_vfs_backend_handle_readonly_lockdown (GVfsBackend *backend)
+{
+ backend->priv->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
+ backend->priv->readonly_lockdown = g_settings_get_boolean (backend->priv->lockdown_settings,
+ "mount-removable-storage-devices-as-read-only");
+ g_signal_connect_object (backend->priv->lockdown_settings,
+ "changed",
+ G_CALLBACK (lockdown_settings_changed),
+ backend,
+ 0);
+}
+
+gboolean
+g_vfs_backend_get_readonly_lockdown (GVfsBackend *backend)
+{
+ return backend->priv->readonly_lockdown;
+}
diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h
index 9c7476cf..431dd290 100644
--- a/daemon/gvfsbackend.h
+++ b/daemon/gvfsbackend.h
@@ -516,6 +516,9 @@ void g_vfs_backend_add_auto_info (GVfsBackend
GFileAttributeMatcher *matcher,
GFileInfo *info,
const char *uri);
+void g_vfs_backend_add_auto_fs_info (GVfsBackend *backend,
+ GFileAttributeMatcher *matcher,
+ GFileInfo *info);
void g_vfs_backend_set_block_requests (GVfsBackend *backend,
gboolean value);
@@ -534,6 +537,9 @@ gboolean g_vfs_backend_invocation_first_handler (GVfsDBusMount *object,
GDBusMethodInvocation *invocation,
GVfsBackend *backend);
+void g_vfs_backend_handle_readonly_lockdown (GVfsBackend *backend);
+gboolean g_vfs_backend_get_readonly_lockdown (GVfsBackend *backend);
+
G_END_DECLS
#endif /* __G_VFS_BACKEND_H__ */
diff --git a/daemon/gvfsbackendafc.c b/daemon/gvfsbackendafc.c
index b6e6a106..ce68aa45 100644
--- a/daemon/gvfsbackendafc.c
+++ b/daemon/gvfsbackendafc.c
@@ -2760,6 +2760,8 @@ g_vfs_backend_afc_init (GVfsBackendAfc *self)
}
g_mutex_init (&self->apps_lock);
+
+ g_vfs_backend_handle_readonly_lockdown (G_VFS_BACKEND (self));
}
static void
diff --git a/daemon/gvfsbackendgphoto2.c b/daemon/gvfsbackendgphoto2.c
index 51e9a3bd..7e50194a 100644
--- a/daemon/gvfsbackendgphoto2.c
+++ b/daemon/gvfsbackendgphoto2.c
@@ -614,6 +614,7 @@ g_vfs_backend_gphoto2_init (GVfsBackendGphoto2 *gphoto2_backend)
g_mutex_init (&gphoto2_backend->lock);
g_vfs_backend_set_display_name (backend, "gphoto2");
+ g_vfs_backend_handle_readonly_lockdown (G_VFS_BACKEND (backend));
mount_spec = g_mount_spec_new ("gphoto2");
g_vfs_backend_set_mount_spec (backend, mount_spec);
diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
index e3a25ef2..c4f1e855 100644
--- a/daemon/gvfsbackendmtp.c
+++ b/daemon/gvfsbackendmtp.c
@@ -379,6 +379,7 @@ g_vfs_backend_mtp_init (GVfsBackendMtp *backend)
g_mutex_init (&backend->mutex);
g_vfs_backend_set_display_name (G_VFS_BACKEND (backend), "mtp");
g_vfs_backend_set_icon_name (G_VFS_BACKEND (backend), "multimedia-player");
+ g_vfs_backend_handle_readonly_lockdown (G_VFS_BACKEND (backend));
mount_spec = g_mount_spec_new ("mtp");
g_vfs_backend_set_mount_spec (G_VFS_BACKEND (backend), mount_spec);
diff --git a/daemon/gvfsjobcopy.c b/daemon/gvfsjobcopy.c
index 785d7480..cf33da56 100644
--- a/daemon/gvfsjobcopy.c
+++ b/daemon/gvfsjobcopy.c
@@ -141,6 +141,13 @@ try (GVfsJob *job)
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
gboolean res;
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_copy == NULL)
return FALSE;
diff --git a/daemon/gvfsjobdelete.c b/daemon/gvfsjobdelete.c
index 92892f15..8d5e5b8e 100644
--- a/daemon/gvfsjobdelete.c
+++ b/daemon/gvfsjobdelete.c
@@ -120,6 +120,13 @@ try (GVfsJob *job)
GVfsJobDelete *op_job = G_VFS_JOB_DELETE (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_delete == NULL)
return FALSE;
diff --git a/daemon/gvfsjobmakedirectory.c b/daemon/gvfsjobmakedirectory.c
index 98bb28d5..56a9c42a 100644
--- a/daemon/gvfsjobmakedirectory.c
+++ b/daemon/gvfsjobmakedirectory.c
@@ -120,6 +120,13 @@ try (GVfsJob *job)
GVfsJobMakeDirectory *op_job = G_VFS_JOB_MAKE_DIRECTORY (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_make_directory == NULL)
return FALSE;
diff --git a/daemon/gvfsjobmakesymlink.c b/daemon/gvfsjobmakesymlink.c
index 2c55e26b..2684b6fd 100644
--- a/daemon/gvfsjobmakesymlink.c
+++ b/daemon/gvfsjobmakesymlink.c
@@ -124,6 +124,13 @@ try (GVfsJob *job)
GVfsJobMakeSymlink *op_job = G_VFS_JOB_MAKE_SYMLINK (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_make_symlink == NULL)
return FALSE;
diff --git a/daemon/gvfsjobmove.c b/daemon/gvfsjobmove.c
index cc4ad220..5903d17a 100644
--- a/daemon/gvfsjobmove.c
+++ b/daemon/gvfsjobmove.c
@@ -141,6 +141,13 @@ try (GVfsJob *job)
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
gboolean res;
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_move == NULL)
return FALSE;
diff --git a/daemon/gvfsjobopenforwrite.c b/daemon/gvfsjobopenforwrite.c
index 68eae532..60ce64f9 100644
--- a/daemon/gvfsjobopenforwrite.c
+++ b/daemon/gvfsjobopenforwrite.c
@@ -230,6 +230,13 @@ try (GVfsJob *job)
GVfsJobOpenForWrite *op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (op_job->mode == OPEN_FOR_WRITE_CREATE)
{
if (class->try_create == NULL)
diff --git a/daemon/gvfsjobpush.c b/daemon/gvfsjobpush.c
index d7e48d86..a8df73a8 100644
--- a/daemon/gvfsjobpush.c
+++ b/daemon/gvfsjobpush.c
@@ -146,6 +146,13 @@ try (GVfsJob *job)
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
gboolean res;
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_push == NULL)
return FALSE;
diff --git a/daemon/gvfsjobqueryfsinfo.c b/daemon/gvfsjobqueryfsinfo.c
index 898052ea..3363311a 100644
--- a/daemon/gvfsjobqueryfsinfo.c
+++ b/daemon/gvfsjobqueryfsinfo.c
@@ -147,15 +147,10 @@ create_reply (GVfsJob *job,
GDBusMethodInvocation *invocation)
{
GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job);
- const char *type;
-
- type = g_vfs_backend_get_backend_type (op_job->backend);
-
- if (type)
- g_file_info_set_attribute_string (op_job->file_info,
- G_FILE_ATTRIBUTE_GVFS_BACKEND,
- type);
+ g_vfs_backend_add_auto_fs_info (op_job->backend,
+ op_job->attribute_matcher,
+ op_job->file_info);
g_file_info_set_attribute_mask (op_job->file_info,
op_job->attribute_matcher);
diff --git a/daemon/gvfsjobsetattribute.c b/daemon/gvfsjobsetattribute.c
index 1efe7c94..ac7618a4 100644
--- a/daemon/gvfsjobsetattribute.c
+++ b/daemon/gvfsjobsetattribute.c
@@ -146,6 +146,13 @@ try (GVfsJob *job)
GVfsJobSetAttribute *op_job = G_VFS_JOB_SET_ATTRIBUTE (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_set_attribute == NULL)
return FALSE;
diff --git a/daemon/gvfsjobsetdisplayname.c b/daemon/gvfsjobsetdisplayname.c
index badb10dd..e12ae879 100644
--- a/daemon/gvfsjobsetdisplayname.c
+++ b/daemon/gvfsjobsetdisplayname.c
@@ -124,6 +124,13 @@ try (GVfsJob *job)
GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_set_display_name == NULL)
return FALSE;
diff --git a/daemon/gvfsjobtrash.c b/daemon/gvfsjobtrash.c
index 1738f8a2..5234ebf8 100644
--- a/daemon/gvfsjobtrash.c
+++ b/daemon/gvfsjobtrash.c
@@ -119,6 +119,13 @@ try (GVfsJob *job)
GVfsJobTrash *op_job = G_VFS_JOB_TRASH (job);
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ if (g_vfs_backend_get_readonly_lockdown (op_job->backend))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Filesystem is read-only"));
+ return TRUE;
+ }
+
if (class->try_trash == NULL)
return FALSE;
--
2.21.0

@ -0,0 +1,99 @@
From 396216f71abf6907efd1383ca0d1a597918cd83d Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Thu, 11 Oct 2018 17:47:59 +0200
Subject: [PATCH] daemon: Prevent spawning new daemons if outgoing operation
exists
A new daemon is always spawned if MountLocation method (or LookupMount for
automounted) is called and the respective mount isn't registered yet. This
is not usually an issue, because the redundant daemons are consequently
terminated. However, this is a problem if mount operations hang for some reason.
This may happen e.g. with trash backend due to stale NFS mounts. Consequently,
new and new daemons are spawned which may lead to system failures due to lack
of system resources. See the following downstream bug report:
https://bugzilla.redhat.com/show_bug.cgi?id=1632960
Let's fix that behavior simply by preventing spawning of new daemons if
respective outgoing mount operations exist.
https://gitlab.gnome.org/GNOME/gvfs/merge_requests/19
---
daemon/mount.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/daemon/mount.c b/daemon/mount.c
index e242666d..33cae597 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -73,6 +73,7 @@ typedef void (*MountCallback) (VfsMountable *mountable,
static GList *mountables = NULL;
static GList *mounts = NULL;
+static GList *ongoing = NULL;
static gboolean fuse_available;
@@ -253,6 +254,7 @@ typedef struct {
char *obj_path;
gboolean spawned;
GVfsDBusSpawner *spawner;
+ GList *pending; /* MountData */
} MountData;
static void spawn_mount (MountData *data);
@@ -264,6 +266,7 @@ mount_data_free (MountData *data)
g_mount_spec_unref (data->mount_spec);
g_free (data->obj_path);
g_clear_object (&data->spawner);
+ g_list_free_full (data->pending, (GDestroyNotify) mount_data_free);
g_free (data);
}
@@ -271,7 +274,17 @@ mount_data_free (MountData *data)
static void
mount_finish (MountData *data, GError *error)
{
+ GList *l;
+
+ ongoing = g_list_remove (ongoing, data);
+
data->callback (data->mountable, error, data->user_data);
+ for (l = data->pending; l != NULL; l = l->next)
+ {
+ MountData *pending_data = l->data;
+ pending_data->callback (pending_data->mountable, error, pending_data->user_data);
+ }
+
mount_data_free (data);
}
@@ -493,6 +506,7 @@ mountable_mount (VfsMountable *mountable,
gpointer user_data)
{
MountData *data;
+ GList *l;
data = g_new0 (MountData, 1);
data->automount = automount;
@@ -502,6 +516,18 @@ mountable_mount (VfsMountable *mountable,
data->callback = callback;
data->user_data = user_data;
+ for (l = ongoing; l != NULL; l = l->next)
+ {
+ MountData *ongoing_data = l->data;
+ if (g_mount_spec_equal (ongoing_data->mount_spec, mount_spec))
+ {
+ ongoing_data->pending = g_list_append (ongoing_data->pending, data);
+ return;
+ }
+ }
+
+ ongoing = g_list_append (ongoing, data);
+
if (mountable->dbus_name == NULL)
spawn_mount (data);
else
--
2.20.1

@ -0,0 +1,164 @@
From bbc95d6716ac491489f059c68a6dd258e38aee79 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Mon, 25 Nov 2019 16:53:31 +0100
Subject: [PATCH] goa: Add support for certificate prompts
Since commit f5ee590e, it is not possible to access Nextcloud/ownCloud
shares with self-signed (or invalid) certificates. This is because
the mount operation is handled by GOA volume monitor and the prompt
to accept certificate is not shown. Let's update the volume monitor
to handle just passwords and show the prompt to the client.
Fixes: https://gitlab.gnome.org/GNOME/gvfs/issues/251
---
monitor/goa/goavolume.c | 98 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 96 insertions(+), 2 deletions(-)
diff --git a/monitor/goa/goavolume.c b/monitor/goa/goavolume.c
index c077dd94..5e9097c6 100644
--- a/monitor/goa/goavolume.c
+++ b/monitor/goa/goavolume.c
@@ -64,6 +64,7 @@ G_DEFINE_TYPE_EXTENDED (GVfsGoaVolume, g_vfs_goa_volume, G_TYPE_OBJECT, 0,
typedef struct
{
GMountOperation *mount_operation;
+ GMountOperation *mount_operation_orig;
gchar *passwd;
} MountOp;
@@ -72,6 +73,13 @@ mount_op_free (MountOp *data)
{
g_clear_object (&data->mount_operation);
g_free (data->passwd);
+
+ if (data->mount_operation_orig != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (data->mount_operation_orig, data);
+ g_object_unref (data->mount_operation_orig);
+ }
+
g_slice_free (MountOp, data);
}
@@ -97,6 +105,88 @@ account_attention_needed_cb (GObject *_object, GParamSpec *pspec, gpointer user_
/* ---------------------------------------------------------------------------------------------------- */
+GType g_vfs_goa_mount_operation_get_type (void) G_GNUC_CONST;
+
+typedef struct
+{
+ GMountOperation parent_instance;
+} GVfsGoaMountOperation;
+
+typedef struct
+{
+ GMountOperationClass parent_class;
+} GVfsGoaMountOperationClass;
+
+static GMountOperation *
+g_vfs_goa_mount_operation_new (void)
+{
+ return G_MOUNT_OPERATION (g_object_new (g_vfs_goa_mount_operation_get_type (), NULL));
+}
+
+G_DEFINE_TYPE (GVfsGoaMountOperation, g_vfs_goa_mount_operation, G_TYPE_MOUNT_OPERATION)
+
+static void
+g_vfs_goa_mount_operation_init (GVfsGoaMountOperation *mount_operation)
+{
+}
+
+static void
+g_vfs_goa_mount_operation_ask_question (GMountOperation *op,
+ const char *message,
+ const char *choices[])
+{
+ /* This is needed to prevent G_MOUNT_OPERATION_UNHANDLED reply in idle. */
+}
+
+static void
+g_vfs_goa_mount_operation_class_init (GVfsGoaMountOperationClass *klass)
+{
+ GMountOperationClass *mount_op_class;
+
+ mount_op_class = G_MOUNT_OPERATION_CLASS (klass);
+ mount_op_class->ask_question = g_vfs_goa_mount_operation_ask_question;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+ask_question_reply_cb (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer user_data)
+{
+ MountOp *data = g_task_get_task_data (user_data);
+
+ g_mount_operation_set_choice (data->mount_operation,
+ g_mount_operation_get_choice (op));
+ g_mount_operation_reply (data->mount_operation, result);
+}
+
+static void
+mount_operation_ask_question_cb (GMountOperation *op,
+ gchar *message,
+ GStrv choices,
+ gpointer user_data)
+{
+ MountOp *data = g_task_get_task_data (user_data);
+
+ if (data->mount_operation_orig != NULL)
+ {
+ g_signal_connect (data->mount_operation_orig,
+ "reply",
+ G_CALLBACK (ask_question_reply_cb),
+ user_data);
+ g_signal_emit_by_name (data->mount_operation_orig,
+ "ask-question",
+ message,
+ choices);
+ }
+ else
+ {
+ g_mount_operation_reply (data->mount_operation,
+ G_MOUNT_OPERATION_UNHANDLED);
+ }
+}
+
static void
mount_operation_ask_password_cb (GMountOperation *op,
gchar *message,
@@ -412,7 +502,7 @@ g_vfs_goa_volume_get_uuid (GVolume *_self)
static void
g_vfs_goa_volume_mount (GVolume *_self,
GMountMountFlags flags,
- GMountOperation *mount_operation,
+ GMountOperation *mount_operation_orig,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -423,6 +513,9 @@ g_vfs_goa_volume_mount (GVolume *_self,
GoaAccount *account;
data = g_slice_new0 (MountOp);
+ if (mount_operation_orig != NULL)
+ data->mount_operation_orig = g_object_ref (mount_operation_orig);
+
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, g_vfs_goa_volume_mount);
g_task_set_task_data (task, data, (GDestroyNotify) mount_op_free);
@@ -431,8 +524,9 @@ g_vfs_goa_volume_mount (GVolume *_self,
* monitor because it is set up to emit MountOpAskPassword on
* ask-password.
*/
- data->mount_operation = g_mount_operation_new ();
+ data->mount_operation = g_vfs_goa_mount_operation_new ();
g_signal_connect (data->mount_operation, "ask-password", G_CALLBACK (mount_operation_ask_password_cb), task);
+ g_signal_connect (data->mount_operation, "ask-question", G_CALLBACK (mount_operation_ask_question_cb), task);
account = goa_object_peek_account (self->object);
goa_account_call_ensure_credentials (account, cancellable, ensure_credentials_cb, task);
--
2.28.0

File diff suppressed because it is too large Load Diff

@ -0,0 +1,92 @@
From e3808a1b4042761055b1d975333a8243d67b8bfe Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 5 Jun 2019 13:33:38 +0100
Subject: [PATCH] gvfsdaemon: Check that the connecting client is the same user
Otherwise, an attacker who learns the abstract socket address from
netstat(8) or similar could connect to it and issue D-Bus method
calls.
Signed-off-by: Simon McVittie <smcv@collabora.com>
---
daemon/gvfsdaemon.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c
index 406d4f8e..be148a7b 100644
--- a/daemon/gvfsdaemon.c
+++ b/daemon/gvfsdaemon.c
@@ -79,6 +79,7 @@ struct _GVfsDaemon
gint mount_counter;
+ GDBusAuthObserver *auth_observer;
GDBusConnection *conn;
GVfsDBusDaemon *daemon_skeleton;
GVfsDBusMountable *mountable_skeleton;
@@ -171,6 +172,8 @@ g_vfs_daemon_finalize (GObject *object)
}
if (daemon->conn != NULL)
g_object_unref (daemon->conn);
+ if (daemon->auth_observer != NULL)
+ g_object_unref (daemon->auth_observer);
g_hash_table_destroy (daemon->registered_paths);
g_hash_table_destroy (daemon->client_connections);
@@ -236,6 +239,35 @@ name_vanished_handler (GDBusConnection *connection,
daemon->lost_main_daemon = TRUE;
}
+/*
+ * Authentication observer signal handler that authorizes connections
+ * from the same uid as this process. This matches the behaviour of a
+ * libdbus DBusServer/DBusConnection when no DBusAllowUnixUserFunction
+ * has been set, but is not the default in GDBus.
+ */
+static gboolean
+authorize_authenticated_peer_cb (GDBusAuthObserver *observer,
+ G_GNUC_UNUSED GIOStream *stream,
+ GCredentials *credentials,
+ G_GNUC_UNUSED gpointer user_data)
+{
+ gboolean authorized = FALSE;
+
+ if (credentials != NULL)
+ {
+ GCredentials *own_credentials;
+
+ own_credentials = g_credentials_new ();
+
+ if (g_credentials_is_same_user (credentials, own_credentials, NULL))
+ authorized = TRUE;
+
+ g_object_unref (own_credentials);
+ }
+
+ return authorized;
+}
+
static void
g_vfs_daemon_init (GVfsDaemon *daemon)
{
@@ -265,6 +297,8 @@ g_vfs_daemon_init (GVfsDaemon *daemon)
daemon->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (daemon->conn != NULL);
+ daemon->auth_observer = g_dbus_auth_observer_new ();
+ g_signal_connect (daemon->auth_observer, "authorize-authenticated-peer", G_CALLBACK (authorize_authenticated_peer_cb), NULL);
daemon->daemon_skeleton = gvfs_dbus_daemon_skeleton_new ();
g_signal_connect (daemon->daemon_skeleton, "handle-get-connection", G_CALLBACK (handle_get_connection), daemon);
@@ -876,7 +910,7 @@ handle_get_connection (GVfsDBusDaemon *object,
server = g_dbus_server_new_sync (address1,
G_DBUS_SERVER_FLAGS_NONE,
guid,
- NULL, /* GDBusAuthObserver */
+ daemon->auth_observer,
NULL, /* GCancellable */
&error);
g_free (guid);
--
2.21.0

@ -0,0 +1,43 @@
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index 33d1a209..776b67bc 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -513,7 +513,13 @@ do_mount (GVfsBackend *backend,
if (res == 0)
break;
- if (op_backend->mount_cancelled || (errsv != EACCES && errsv != EPERM))
+ if (errsv == EINVAL && op_backend->mount_try == 0 && op_backend->user == NULL)
+ {
+ /* EINVAL is "expected" when kerberos/ccache is misconfigured, see:
+ * https://gitlab.gnome.org/GNOME/gvfs/-/issues/611
+ */
+ }
+ else if (op_backend->mount_cancelled || (errsv != EACCES && errsv != EPERM))
{
g_debug ("do_mount - (errno != EPERM && errno != EACCES), cancelled = %d, breaking\n", op_backend->mount_cancelled);
break;
diff --git a/daemon/gvfsbackendsmbbrowse.c b/daemon/gvfsbackendsmbbrowse.c
index 57bae9db..7e8facfb 100644
--- a/daemon/gvfsbackendsmbbrowse.c
+++ b/daemon/gvfsbackendsmbbrowse.c
@@ -967,8 +967,14 @@ do_mount (GVfsBackend *backend,
uri, op_backend->mount_try, dir, op_backend->mount_cancelled,
errsv, g_strerror (errsv));
- if (dir == NULL &&
- (op_backend->mount_cancelled || (errsv != EPERM && errsv != EACCES)))
+ if (errsv == EINVAL && op_backend->mount_try == 0 && op_backend->user == NULL)
+ {
+ /* EINVAL is "expected" when kerberos is misconfigured, see:
+ * https://gitlab.gnome.org/GNOME/gvfs/-/issues/611
+ */
+ }
+ else if (dir == NULL &&
+ (op_backend->mount_cancelled || (errsv != EPERM && errsv != EACCES)))
{
g_debug ("do_mount - (errno != EPERM && errno != EACCES), cancelled = %d, breaking\n", op_backend->mount_cancelled);
break;
--
2.35.1

@ -0,0 +1,115 @@
diff --git a/configure.ac b/configure.ac
index daeee728..689667e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -551,6 +551,11 @@ if test "x$enable_samba" != "xno"; then
AC_DEFINE(HAVE_SMBC_SETOPTIONPROTOCOLS, 1, [Define to 1 if smbc_setOptionProtocols() is available]),
[]
)
+
+ AC_CHECK_LIB(smbclient, smbc_readdirplus2,
+ AC_DEFINE(HAVE_SMBC_READDIRPLUS2, 1, [Define to 1 if smbc_readdirplus2() is available]),
+ []
+ )
fi
fi
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index 9571fa0d..ce151648 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -1738,25 +1738,34 @@ do_enumerate (GVfsBackend *backend,
GFileQueryInfoFlags flags)
{
GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
- struct stat st;
- int res;
+ struct stat st = { 0 };
GError *error;
SMBCFILE *dir;
- char dirents[1024*4];
- struct smbc_dirent *dirp;
GFileInfo *info;
GString *uri;
- int uri_start_len;
smbc_opendir_fn smbc_opendir;
+ smbc_closedir_fn smbc_closedir;
+#ifndef HAVE_SMBC_READDIRPLUS2
+ int res;
+ char dirents[1024*4];
+ struct smbc_dirent *dirp;
+ int uri_start_len;
smbc_getdents_fn smbc_getdents;
smbc_stat_fn smbc_stat;
- smbc_closedir_fn smbc_closedir;
+#else
+ smbc_readdirplus2_fn smbc_readdirplus2;
+ const struct libsmb_file_info *exstat;
+#endif
uri = create_smb_uri_string (op_backend->server, op_backend->port, op_backend->share, filename);
smbc_opendir = smbc_getFunctionOpendir (op_backend->smb_context);
+#ifndef HAVE_SMBC_READDIRPLUS2
smbc_getdents = smbc_getFunctionGetdents (op_backend->smb_context);
smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+#else
+ smbc_readdirplus2 = smbc_getFunctionReaddirPlus2 (op_backend->smb_context);
+#endif
smbc_closedir = smbc_getFunctionClosedir (op_backend->smb_context);
dir = smbc_opendir (op_backend->smb_context, uri->str);
@@ -1776,6 +1785,8 @@ do_enumerate (GVfsBackend *backend,
if (uri->str[uri->len - 1] != '/')
g_string_append_c (uri, '/');
+
+#ifndef HAVE_SMBC_READDIRPLUS2
uri_start_len = uri->len;
while (TRUE)
@@ -1827,9 +1838,27 @@ do_enumerate (GVfsBackend *backend,
dirp = (struct smbc_dirent *) (((char *)dirp) + dirlen);
res -= dirlen;
}
+ }
+#else
+ while ((exstat = smbc_readdirplus2 (op_backend->smb_context, dir, &st)) != NULL)
+ {
+ if ((S_ISREG (st.st_mode) ||
+ S_ISDIR (st.st_mode) ||
+ S_ISLNK (st.st_mode)) &&
+ g_strcmp0 (exstat->name, ".") != 0 &&
+ g_strcmp0 (exstat->name, "..") != 0)
+ {
+ info = g_file_info_new ();
+ set_info_from_stat (op_backend, info, &st, exstat->name, matcher);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ memset (&st, 0, sizeof (struct stat));
}
-
- res = smbc_closedir (op_backend->smb_context, dir);
+#endif
+
+ smbc_closedir (op_backend->smb_context, dir);
g_vfs_job_enumerate_done (job);
diff --git a/meson.build b/meson.build
index 6ae768d9..d3f59457 100644
--- a/meson.build
+++ b/meson.build
@@ -418,6 +418,7 @@ if enable_samba
smbclient_dep = dependency('smbclient')
config_h.set('HAVE_SMBC_SETOPTIONPROTOCOLS', cc.has_function('smbc_setOptionProtocols', dependencies: smbclient_dep))
+ config_h.set('HAVE_SMBC_READDIRPLUS2', cc.has_function('smbc_readdirplus2', dependencies: smbclient_dep))
endif
# *** Check for libarchive ***
--
2.26.2

@ -0,0 +1,57 @@
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index 776b67bc..a1e3eacd 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -80,7 +80,6 @@ struct _GVfsBackendSmb
int mount_try;
gboolean mount_try_again;
gboolean mount_cancelled;
- gboolean use_anonymous;
gboolean password_in_keyring;
GPasswordSave password_save;
@@ -215,13 +214,6 @@ auth_callback (SMBCCTX *context,
backend->mount_try_again = TRUE;
g_debug ("auth_callback - kerberos pass\n");
}
- else if (backend->use_anonymous)
- {
- /* Try again if anonymous login fails */
- backend->use_anonymous = FALSE;
- backend->mount_try_again = TRUE;
- g_debug ("auth_callback - anonymous login pass\n");
- }
else
{
gboolean in_keyring = FALSE;
@@ -304,10 +296,13 @@ auth_callback (SMBCCTX *context,
/* Try again if this fails */
backend->mount_try_again = TRUE;
+ smbc_setOptionNoAutoAnonymousLogin (backend->smb_context,
+ !anonymous);
+
if (anonymous)
{
- backend->use_anonymous = TRUE;
backend->password_save = FALSE;
+ g_debug ("auth_callback - anonymous enabled\n");
}
else
{
@@ -535,12 +530,6 @@ do_mount (GVfsBackend *backend,
smbc_setOptionFallbackAfterKerberos (op_backend->smb_context, 1);
}
- /* If the AskPassword reply requested anonymous login, enable the
- * anonymous fallback and try again.
- */
- smbc_setOptionNoAutoAnonymousLogin (op_backend->smb_context,
- !op_backend->use_anonymous);
-
op_backend->mount_try ++;
}
while (op_backend->mount_try_again);
--
2.36.0

@ -0,0 +1,67 @@
From 3f6f906c7c7b28dc30edb98200b6e13e1a513bb4 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Wed, 9 May 2018 12:54:59 +0200
Subject: [PATCH] smb: Use O_RDWR to fix fstat when writing
fstat fails with EINVAL on Windows servers if O_WRONLY is used to open
(though it works properly on SAMBA servers). O_RDWR is needed to make
it work. This causes issues when copying files over gvfsd-fuse among
others.
https://bugzilla.gnome.org/show_bug.cgi?id=795805
---
daemon/gvfsbackendsmb.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index d4944197..9571fa0d 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -808,7 +808,7 @@ do_create (GVfsBackend *backend,
smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
errno = 0;
file = smbc_open (op_backend->smb_context, uri,
- O_CREAT|O_WRONLY|O_EXCL, 0666);
+ O_CREAT|O_RDWR|O_EXCL, 0666);
g_free (uri);
if (file == NULL)
@@ -850,7 +850,7 @@ do_append_to (GVfsBackend *backend,
smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
errno = 0;
file = smbc_open (op_backend->smb_context, uri,
- O_CREAT|O_WRONLY|O_APPEND, 0666);
+ O_CREAT|O_RDWR|O_APPEND, 0666);
g_free (uri);
if (file == NULL)
@@ -916,7 +916,7 @@ open_tmpfile (GVfsBackendSmb *backend,
smbc_open = smbc_getFunctionOpen (backend->smb_context);
errno = 0;
file = smbc_open (backend->smb_context, tmp_uri,
- O_CREAT|O_WRONLY|O_EXCL, 0666);
+ O_CREAT|O_RDWR|O_EXCL, 0666);
} while (file == NULL && errno == EEXIST);
g_free (dir_uri);
@@ -1040,7 +1040,7 @@ do_replace (GVfsBackend *backend,
errno = 0;
file = smbc_open (op_backend->smb_context, uri,
- O_CREAT|O_WRONLY|O_EXCL, 0);
+ O_CREAT|O_RDWR|O_EXCL, 0);
if (file == NULL && errno != EEXIST)
{
int errsv = fixup_open_errno (errno);
@@ -1110,7 +1110,7 @@ do_replace (GVfsBackend *backend,
errno = 0;
file = smbc_open (op_backend->smb_context, uri,
- O_CREAT|O_WRONLY|O_TRUNC, 0);
+ O_CREAT|O_RDWR|O_TRUNC, 0);
if (file == NULL)
{
int errsv = fixup_open_errno (errno);
--
2.35.3

@ -0,0 +1,89 @@
diff --git a/configure.ac b/configure.ac
index 3b5836ff..daeee728 100644
--- a/configure.ac
+++ b/configure.ac
@@ -546,6 +546,11 @@ if test "x$enable_samba" != "xno"; then
if test "x$msg_samba" = "xyes"; then
PKG_CHECK_MODULES([SAMBA], [smbclient])
AC_DEFINE([HAVE_SAMBA], 1, [Define to 1 if you have the samba libraries])
+
+ AC_CHECK_LIB(smbclient, smbc_setOptionProtocols,
+ AC_DEFINE(HAVE_SMBC_SETOPTIONPROTOCOLS, 1, [Define to 1 if smbc_setOptionProtocols() is available]),
+ []
+ )
fi
fi
diff --git a/daemon/gvfsbackendsmbbrowse.c b/daemon/gvfsbackendsmbbrowse.c
index f08d2988..3b11883e 100644
--- a/daemon/gvfsbackendsmbbrowse.c
+++ b/daemon/gvfsbackendsmbbrowse.c
@@ -45,6 +45,7 @@
#include "gvfskeyring.h"
#include "gmounttracker.h"
#include "gvfsbackendsmbprivate.h"
+#include "gvfsutils.h"
#include <libsmbclient.h>
@@ -847,6 +848,47 @@ do_mount (GVfsBackend *backend,
else
op_backend->server = g_strdup (op_backend->mounted_server);
+#ifdef HAVE_SMBC_SETOPTIONPROTOCOLS
+ /* Force NT1 protocol version if server can't be resolved (i.e. is not
+ * hostname, nor IP address). This is needed for workgroup support, because
+ * "client max protocol" has been changed from NT1 to SMB3 in recent samba
+ * versions.
+ */
+
+ if (op_backend->server != NULL)
+ {
+ GResolver *resolver;
+ GList *addresses;
+ GError *error = NULL;
+ gchar *server;
+
+ resolver = g_resolver_get_default ();
+
+ /* IPv6 server includes brackets in GMountSpec, GResolver doesn't */
+ if (gvfs_is_ipv6 (op_backend->server))
+ server = g_strndup (op_backend->server + 1, strlen (op_backend->server) - 2);
+ else
+ server = g_strdup (op_backend->server);
+
+ addresses = g_resolver_lookup_by_name (resolver, server, NULL, &error);
+ if (addresses == NULL)
+ {
+ if (error != NULL)
+ {
+ g_debug ("%s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_debug ("Forcing NT1 protocol version\n");
+ smbc_setOptionProtocols (smb_context, "NT1", "NT1");
+ }
+
+ g_resolver_free_addresses (addresses);
+ g_object_unref (resolver);
+ g_free (server);
+ }
+#endif
+
icon = NULL;
symbolic_icon = NULL;
if (op_backend->server == NULL)
diff --git a/meson.build b/meson.build
index 34600188..3a876172 100644
--- a/meson.build
+++ b/meson.build
@@ -416,6 +416,8 @@ config_h.set10('HAVE_LIBUSB', enable_libusb)
enable_samba = get_option('smb')
if enable_samba
smbclient_dep = dependency('smbclient')
+
+ config_h.set('HAVE_SMBC_SETOPTIONPROTOCOLS', cc.has_function('smbc_setOptionProtocols', dependencies: smbclient_dep))
endif
# *** Check for libarchive ***

@ -0,0 +1,65 @@
From f93bd46c36c8e42f17f0f61b79c55a3794906395 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Fri, 6 Mar 2020 10:08:09 +0100
Subject: [PATCH] trash: Add support for x-gvfs-notrash option to ignore mounts
Add support for x-gvfs-notrash mount option, which allows to ignore
trash folder on certain mounts. This might be especially useful e.g.
to prevent wakeups of autofs mounts...
https://bugzilla.redhat.com/show_bug.cgi?id=1096200
---
daemon/trashlib/trashwatcher.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
index 6b455235..01c440a1 100644
--- a/daemon/trashlib/trashwatcher.c
+++ b/daemon/trashlib/trashwatcher.c
@@ -211,6 +211,34 @@ trash_mount_remove (TrashMount **mount_ptr)
g_slice_free (TrashMount, mount);
}
+static gboolean
+ignore_trash_mount (GUnixMountEntry *mount)
+{
+ GUnixMountPoint *mount_point = NULL;
+ const gchar *mount_options;
+ gboolean retval = TRUE;
+
+ if (g_unix_mount_is_system_internal (mount))
+ return TRUE;
+
+ mount_options = g_unix_mount_get_options (mount);
+ if (mount_options == NULL)
+ {
+ mount_point = g_unix_mount_point_at (g_unix_mount_get_mount_path (mount),
+ NULL);
+ if (mount_point != NULL)
+ mount_options = g_unix_mount_point_get_options (mount_point);
+ }
+
+ if (mount_options == NULL ||
+ strstr (mount_options, "x-gvfs-notrash") == NULL)
+ retval = FALSE;
+
+ g_clear_pointer (&mount_point, g_unix_mount_point_free);
+
+ return retval;
+}
+
static void
trash_watcher_remount (TrashWatcher *watcher)
{
@@ -229,7 +257,7 @@ trash_watcher_remount (TrashWatcher *watcher)
{
int result;
- if (new && g_unix_mount_is_system_internal (new->data))
+ if (new && ignore_trash_mount (new->data))
{
g_unix_mount_free (new->data);
new = new->next;
--
2.41.0

@ -0,0 +1,55 @@
From 41862c0179f834d8bc3bd84ce78ee495050f2676 Mon Sep 17 00:00:00 2001
From: rong wang <wangrong@uniontech.com>
Date: Thu, 23 Mar 2023 10:26:24 +0800
Subject: [PATCH] trash: Sync trash dir items when files change
In the case of an application monitoring the trash can, delete a file
on the mounted device to the trash can, and then unmount the device.
At this time, if you check the status of the trash can, you will find
that the number of files queried is inconsistent with the number of
files obtained through the enumeration job. This is because the number
of files queried includes some files that do not exist when the device
is unmounted. The solution is to synchronize the status of the trash
can in time to ensure that the trash can does not record files that do
not exist.
---
daemon/trashlib/trashdir.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/daemon/trashlib/trashdir.c b/daemon/trashlib/trashdir.c
index c470d3bd..0d7d2b1b 100644
--- a/daemon/trashlib/trashdir.c
+++ b/daemon/trashlib/trashdir.c
@@ -163,10 +163,27 @@ trash_dir_changed (GFileMonitor *monitor,
TrashDir *dir = user_data;
if (event_type == G_FILE_MONITOR_EVENT_CREATED)
- trash_root_add_item (dir->root, file, dir->topdir, dir->is_homedir);
+ {
+ dir->items = g_slist_insert_sorted (dir->items,
+ g_object_ref (file),
+ (GCompareFunc) compare_basename);
+ trash_root_add_item (dir->root, file, dir->topdir, dir->is_homedir);
+ }
else if (event_type == G_FILE_MONITOR_EVENT_DELETED)
- trash_root_remove_item (dir->root, file, dir->is_homedir);
+ {
+ GSList *node;
+
+ node = g_slist_find_custom (dir->items,
+ file,
+ (GCompareFunc) compare_basename);
+ if (node)
+ {
+ g_object_unref (node->data);
+ dir->items = g_slist_delete_link (dir->items, node);
+ }
+ trash_root_remove_item (dir->root, file, dir->is_homedir);
+ }
else if (event_type == G_FILE_MONITOR_EVENT_PRE_UNMOUNT ||
event_type == G_FILE_MONITOR_EVENT_UNMOUNTED ||
--
2.41.0

@ -0,0 +1,29 @@
From 38831e4ea149a0b4731d123c63d8b493d30ad0be Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Sat, 26 May 2018 08:16:02 +0200
Subject: [PATCH] udisks2: Fix crashes caused by missing source tag
GAsyncReadyCallback is never called from g_drive_stop, because
source_tag is not set, but checked. This obviously causes issues
for client applications. Add missing source_tag.
Closes: https://gitlab.gnome.org/GNOME/gvfs/issues/1
---
monitor/udisks2/gvfsudisks2drive.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/monitor/udisks2/gvfsudisks2drive.c b/monitor/udisks2/gvfsudisks2drive.c
index 52e9b75e..87656688 100644
--- a/monitor/udisks2/gvfsudisks2drive.c
+++ b/monitor/udisks2/gvfsudisks2drive.c
@@ -915,6 +915,7 @@ gvfs_udisks2_drive_stop (GDrive *_drive,
GTask *task;
task = g_task_new (drive, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gvfs_udisks2_drive_stop);
/* This information is needed in GVfsDdisks2Volume when apps have
* open files on the device ... we need to know if the button should
--
2.23.0

@ -0,0 +1,128 @@
From 9fdd59cfda93b508e76770146a8295d0a26b175d Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Tue, 14 May 2019 08:46:48 +0200
Subject: [PATCH 1/3] udisks2: Handle lockdown option to disable writing
Handle the new mount-removable-storage-devices-as-read-only option of
org.gnome.desktop.lockdown schema and mount removable devices as read-only
if enabled.
---
monitor/udisks2/gvfsudisks2volume.c | 8 +++++
monitor/udisks2/gvfsudisks2volumemonitor.c | 34 ++++++++++++++++++++++
monitor/udisks2/gvfsudisks2volumemonitor.h | 1 +
3 files changed, 43 insertions(+)
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index a509b5dd..b2545058 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -1093,6 +1093,7 @@ do_mount (GTask *task)
{
MountData *data = g_task_get_task_data (task);
GVariantBuilder builder;
+ GVfsUDisks2Volume *volume = g_task_get_source_object (task);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (data->mount_operation == NULL)
@@ -1101,6 +1102,13 @@ do_mount (GTask *task)
"{sv}",
"auth.no_user_interaction", g_variant_new_boolean (TRUE));
}
+ if (gvfs_udisks2_volume_monitor_get_readonly_lockdown (volume->monitor))
+ {
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "options", g_variant_new_string ("ro"));
+
+ }
udisks_filesystem_call_mount (data->filesystem_to_mount,
g_variant_builder_end (&builder),
g_task_get_cancellable (task),
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index 0a5ce96e..37c81fcf 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -65,6 +65,9 @@ struct _GVfsUDisks2VolumeMonitor
/* we keep volumes/mounts for blank and audio discs separate to handle e.g. mixed discs properly */
GList *disc_volumes;
GList *disc_mounts;
+
+ GSettings *lockdown_settings;
+ gboolean readonly_lockdown;
};
static UDisksClient *get_udisks_client_sync (GError **error);
@@ -140,6 +143,8 @@ gvfs_udisks2_volume_monitor_finalize (GObject *object)
g_list_free_full (monitor->disc_volumes, g_object_unref);
g_list_free_full (monitor->disc_mounts, g_object_unref);
+ g_clear_object (&monitor->lockdown_settings);
+
G_OBJECT_CLASS (gvfs_udisks2_volume_monitor_parent_class)->finalize (object);
}
@@ -304,6 +309,17 @@ gvfs_udisks2_volume_monitor_constructor (GType type,
return ret;
}
+static void
+lockdown_settings_changed (GSettings *settings,
+ gchar *key,
+ gpointer user_data)
+{
+ GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
+
+ monitor->readonly_lockdown = g_settings_get_boolean (settings,
+ "mount-removable-storage-devices-as-read-only");
+}
+
static void
gvfs_udisks2_volume_monitor_init (GVfsUDisks2VolumeMonitor *monitor)
{
@@ -325,6 +341,15 @@ gvfs_udisks2_volume_monitor_init (GVfsUDisks2VolumeMonitor *monitor)
G_CALLBACK (mountpoints_changed),
monitor);
+ monitor->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
+ monitor->readonly_lockdown = g_settings_get_boolean (monitor->lockdown_settings,
+ "mount-removable-storage-devices-as-read-only");
+ g_signal_connect_object (monitor->lockdown_settings,
+ "changed",
+ G_CALLBACK (lockdown_settings_changed),
+ monitor,
+ 0);
+
update_all (monitor, FALSE, TRUE);
}
@@ -388,6 +413,15 @@ gvfs_udisks2_volume_monitor_get_gudev_client (GVfsUDisks2VolumeMonitor *monitor)
/* ---------------------------------------------------------------------------------------------------- */
+gboolean
+gvfs_udisks2_volume_monitor_get_readonly_lockdown (GVfsUDisks2VolumeMonitor *monitor)
+{
+ g_return_val_if_fail (GVFS_IS_UDISKS2_VOLUME_MONITOR (monitor), FALSE);
+ return monitor->readonly_lockdown;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
void
gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor)
{
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.h b/monitor/udisks2/gvfsudisks2volumemonitor.h
index 7f0215dc..751a0236 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.h
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.h
@@ -49,6 +49,7 @@ GVolumeMonitor *gvfs_udisks2_volume_monitor_new (void);
UDisksClient *gvfs_udisks2_volume_monitor_get_udisks_client (GVfsUDisks2VolumeMonitor *monitor);
void gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor);
GUdevClient *gvfs_udisks2_volume_monitor_get_gudev_client (GVfsUDisks2VolumeMonitor *monitor);
+gboolean gvfs_udisks2_volume_monitor_get_readonly_lockdown (GVfsUDisks2VolumeMonitor *monitor);
G_END_DECLS
--
2.21.0

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save