mirror of
https://github.com/ublue-os/bazzite.git
synced 2025-03-12 04:14:06 +00:00
chore: Add additional patch to udisks2
This commit is contained in:
parent
1558ecd587
commit
5cafd330ef
351
spec_files/udisks2/mount-other-user.patch
Normal file
351
spec_files/udisks2/mount-other-user.patch
Normal file
@ -0,0 +1,351 @@
|
||||
From ae24405030d6759f209a19d2eedaf5060715701a Mon Sep 17 00:00:00 2001
|
||||
From: Alberto Garcia <berto@igalia.com>
|
||||
Date: Wed, 8 Mar 2023 18:00:34 +0100
|
||||
Subject: [PATCH] Extend Filesystem.Mount() to allow mounting on behalf of
|
||||
another user
|
||||
|
||||
Filesystems are mounted for the user who makes the D-Bus API call.
|
||||
This has an effect on a few things, notably who has permissions
|
||||
to unmount it later and also the path of the mount point, usually in
|
||||
the form of /run/media/USER/LABEL
|
||||
|
||||
This patch adds a new parameter to the Filesystem.Mount() method that
|
||||
allows mounting a filesystem on behalf of a different user.
|
||||
|
||||
Fixes #1065
|
||||
|
||||
(cherry picked from commit 2fddf2b951b993303fe07813ad2398ab91937911)
|
||||
---
|
||||
data/org.freedesktop.UDisks2.policy.in | 11 +++
|
||||
data/org.freedesktop.UDisks2.xml | 8 ++-
|
||||
src/tests/dbus-tests/test_80_filesystem.py | 80 ++++++++++++++++++++++
|
||||
src/udisksdaemonutil.c | 53 ++++++++++++++
|
||||
src/udisksdaemonutil.h | 6 ++
|
||||
src/udiskslinuxfilesystem.c | 60 ++++++++++++----
|
||||
6 files changed, 202 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/data/org.freedesktop.UDisks2.policy.in b/data/org.freedesktop.UDisks2.policy.in
|
||||
index 4b02f46f..816620d7 100644
|
||||
--- a/data/org.freedesktop.UDisks2.policy.in
|
||||
+++ b/data/org.freedesktop.UDisks2.policy.in
|
||||
@@ -44,6 +44,17 @@
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
+ <!-- mount a device on behalf of another user -->
|
||||
+ <action id="org.freedesktop.udisks2.filesystem-mount-other-user">
|
||||
+ <description>Mount a filesystem on behalf of another user</description>
|
||||
+ <message>Authentication is required to mount the filesystem</message>
|
||||
+ <defaults>
|
||||
+ <allow_any>auth_admin</allow_any>
|
||||
+ <allow_inactive>auth_admin</allow_inactive>
|
||||
+ <allow_active>auth_admin_keep</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+
|
||||
<!-- mount a device referenced in the /etc/fstab file with the x-udisks-auth option -->
|
||||
<action id="org.freedesktop.udisks2.filesystem-fstab">
|
||||
<description>Mount/unmount filesystems defined in the fstab file with the x-udisks-auth option</description>
|
||||
diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml
|
||||
index a3ea4901..2a1704ee 100644
|
||||
--- a/data/org.freedesktop.UDisks2.xml
|
||||
+++ b/data/org.freedesktop.UDisks2.xml
|
||||
@@ -1853,7 +1853,7 @@
|
||||
|
||||
<!--
|
||||
Mount:
|
||||
- @options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>fstype</parameter> (of type 's') and <parameter>options</parameter> (of type 's').
|
||||
+ @options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>fstype</parameter> (of type 's'), <parameter>as-user</parameter> (of type 's') and <parameter>options</parameter> (of type 's').
|
||||
@mount_path: The filesystem path where the device was mounted.
|
||||
|
||||
Mounts the filesystem.
|
||||
@@ -1875,6 +1875,12 @@
|
||||
filesystem types are validated against a (small) whitelist to
|
||||
avoid unexpected privilege escalation
|
||||
|
||||
+ If the <parameter>as-user</parameter> option is set, the
|
||||
+ filesystem is mounted on behalf of the specified user instead
|
||||
+ of the calling one. This has usually an effect on the returned
|
||||
+ @mount_path and it also allows that user to unmount the
|
||||
+ filesystem later. This option expects a user name, not a UID.
|
||||
+
|
||||
If the device in question is referenced in the
|
||||
<filename>/etc/fstab</filename> file, the
|
||||
<command>mount</command> command is called directly (as root)
|
||||
diff --git a/src/tests/dbus-tests/test_80_filesystem.py b/src/tests/dbus-tests/test_80_filesystem.py
|
||||
index c16d32ca..babc85f3 100644
|
||||
--- a/src/tests/dbus-tests/test_80_filesystem.py
|
||||
+++ b/src/tests/dbus-tests/test_80_filesystem.py
|
||||
@@ -648,6 +648,86 @@ class UdisksFSTestCase(udiskstestcase.UdisksTestCase):
|
||||
|
||||
|
||||
|
||||
+ def _unmount_as_user(self, pipe, uid, gid, device):
|
||||
+ """ Try to unmount @device as user with given @uid and @gid."""
|
||||
+ os.setresgid(gid, gid, gid)
|
||||
+ os.setresuid(uid, uid, uid)
|
||||
+
|
||||
+ try:
|
||||
+ safe_dbus.call_sync(self.iface_prefix,
|
||||
+ self.path_prefix + '/block_devices/' + os.path.basename(device),
|
||||
+ self.iface_prefix + '.Filesystem',
|
||||
+ 'Unmount',
|
||||
+ GLib.Variant('(a{sv})', ({},)))
|
||||
+ except Exception as e:
|
||||
+ pipe.send([False, 'Unmount DBus call failed: %s' % str(e)])
|
||||
+ pipe.close()
|
||||
+ return
|
||||
+
|
||||
+ pipe.send([True, ''])
|
||||
+ pipe.close()
|
||||
+
|
||||
+ @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
|
||||
+ def test_mount_as_user(self):
|
||||
+ """ Test mounting a filesystem on behalf of a different user."""
|
||||
+ if not self._can_create:
|
||||
+ self.skipTest('Cannot create %s filesystem' % self._fs_name)
|
||||
+
|
||||
+ if not self._can_label:
|
||||
+ self.skipTest('Cannot set label when creating %s filesystem' % self._fs_name)
|
||||
+
|
||||
+ if not self._can_mount:
|
||||
+ self.skipTest('Cannot mount %s filesystem' % self._fs_name)
|
||||
+
|
||||
+ disk = self.get_object('/block_devices/' + os.path.basename(self.vdevs[0]))
|
||||
+ self.assertIsNotNone(disk)
|
||||
+
|
||||
+ # create filesystem with label
|
||||
+ d = dbus.Dictionary(signature='sv')
|
||||
+ d['label'] = 'UDISKS'
|
||||
+ disk.Format(self._fs_name, d, dbus_interface=self.iface_prefix + '.Block')
|
||||
+ self.addCleanup(self.wipe_fs, self.vdevs[0])
|
||||
+
|
||||
+ # get real block object for the newly created filesystem
|
||||
+ block_fs, block_fs_dev = self._get_formatted_block_object(self.vdevs[0])
|
||||
+ self.assertIsNotNone(block_fs)
|
||||
+ self.assertIsNotNone(block_fs_dev)
|
||||
+
|
||||
+ # create user for our test
|
||||
+ self.addCleanup(self._remove_user, self.username)
|
||||
+ uid, gid = self._add_user(self.username)
|
||||
+
|
||||
+ # prepare the mount options
|
||||
+ d = dbus.Dictionary(signature='sv')
|
||||
+ d['options'] = 'ro'
|
||||
+ if self._fs_name:
|
||||
+ d['fstype'] = self._fs_name
|
||||
+
|
||||
+ # try to mount it now: first with a nonexistent user
|
||||
+ d['as-user'] = 'nonexistent'
|
||||
+ with six.assertRaisesRegex(self, dbus.exceptions.DBusException, "User with name nonexistent does not exist"):
|
||||
+ block_fs.Mount(d, dbus_interface=self.iface_prefix + '.Filesystem')
|
||||
+
|
||||
+ # now mount it with the actual user
|
||||
+ d['as-user'] = self.username
|
||||
+ mnt_path = block_fs.Mount(d, dbus_interface=self.iface_prefix + '.Filesystem')
|
||||
+ self.addCleanup(self.try_unmount, block_fs_dev)
|
||||
+ self.addCleanup(self.try_unmount, self.vdevs[0])
|
||||
+
|
||||
+ # check that the name of the mount point matches the expectation
|
||||
+ self.assertTrue(mnt_path.endswith("%s/UDISKS" % self.username))
|
||||
+
|
||||
+ # try to unmount it as the other user
|
||||
+ parent_conn, child_conn = Pipe()
|
||||
+ proc = Process(target=self._unmount_as_user, args=(child_conn, int(uid), int(gid), block_fs_dev))
|
||||
+ proc.start()
|
||||
+ res = parent_conn.recv()
|
||||
+ parent_conn.close()
|
||||
+ proc.join()
|
||||
+
|
||||
+ if not res[0]:
|
||||
+ self.fail(res[1])
|
||||
+
|
||||
class Ext2TestCase(UdisksFSTestCase):
|
||||
_fs_name = 'ext2'
|
||||
_can_create = True and UdisksFSTestCase.command_exists('mke2fs')
|
||||
diff --git a/src/udisksdaemonutil.c b/src/udisksdaemonutil.c
|
||||
index 1695b524..f7cc865d 100644
|
||||
--- a/src/udisksdaemonutil.c
|
||||
+++ b/src/udisksdaemonutil.c
|
||||
@@ -1080,6 +1080,59 @@ out:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * udisks_daemon_util_get_user_info_by_name:
|
||||
+ * @out_uid: (out) (allow-none): Return location for resolved uid or %NULL.
|
||||
+ * @out_gid: (out) (allow-none): Return location for resolved gid or %NULL.
|
||||
+ * @error: Return location for error.
|
||||
+ *
|
||||
+ * Gets the UNIX id and group for a user name.
|
||||
+ *
|
||||
+ * Returns: %TRUE if the user information was obtained, %FALSE otherwise
|
||||
+ */
|
||||
+gboolean
|
||||
+udisks_daemon_util_get_user_info_by_name (const gchar *user_name,
|
||||
+ uid_t *out_uid,
|
||||
+ gid_t *out_gid,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ struct passwd pwstruct;
|
||||
+ gchar pwbuf[8192];
|
||||
+ struct passwd *pw = NULL;
|
||||
+ int rc;
|
||||
+
|
||||
+ g_return_val_if_fail (user_name != NULL, FALSE);
|
||||
+
|
||||
+ rc = getpwnam_r (user_name, &pwstruct, pwbuf, sizeof pwbuf, &pw);
|
||||
+ if (rc == 0 && pw == NULL)
|
||||
+ {
|
||||
+ g_set_error (error,
|
||||
+ UDISKS_ERROR,
|
||||
+ UDISKS_ERROR_FAILED,
|
||||
+ "User with name %s does not exist", user_name);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ else if (pw == NULL)
|
||||
+ {
|
||||
+ g_set_error (error,
|
||||
+ UDISKS_ERROR,
|
||||
+ UDISKS_ERROR_FAILED,
|
||||
+ "Error looking up passwd struct for user %s: %m", user_name);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (out_uid != NULL)
|
||||
+ *out_uid = pw->pw_uid;
|
||||
+
|
||||
+ if (out_gid != NULL)
|
||||
+ *out_gid = pw->pw_gid;
|
||||
+
|
||||
+ return TRUE;
|
||||
+
|
||||
+out:
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* udisks_daemon_util_get_caller_uid_sync:
|
||||
* @daemon: A #UDisksDaemon.
|
||||
diff --git a/src/udisksdaemonutil.h b/src/udisksdaemonutil.h
|
||||
index df584de4..cd263c76 100644
|
||||
--- a/src/udisksdaemonutil.h
|
||||
+++ b/src/udisksdaemonutil.h
|
||||
@@ -94,6 +94,12 @@ gboolean udisks_daemon_util_get_user_info (const uid_t uid,
|
||||
gchar **out_user_name,
|
||||
GError **error);
|
||||
|
||||
+gboolean
|
||||
+udisks_daemon_util_get_user_info_by_name (const gchar *user_name,
|
||||
+ uid_t *out_uid,
|
||||
+ gid_t *out_gid,
|
||||
+ GError **error);
|
||||
+
|
||||
gboolean udisks_daemon_util_get_caller_uid_sync (UDisksDaemon *daemon,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GCancellable *cancellable,
|
||||
diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c
|
||||
index 619e0b85..92d3ab37 100644
|
||||
--- a/src/udiskslinuxfilesystem.c
|
||||
+++ b/src/udiskslinuxfilesystem.c
|
||||
@@ -795,6 +795,7 @@ handle_mount (UDisksFilesystem *filesystem,
|
||||
UDisksBlock *block;
|
||||
UDisksDaemon *daemon;
|
||||
UDisksState *state = NULL;
|
||||
+ gchar *opt_as_user = NULL;
|
||||
uid_t caller_uid;
|
||||
gid_t caller_gid;
|
||||
const gchar * const *existing_mount_points;
|
||||
@@ -824,6 +825,14 @@ handle_mount (UDisksFilesystem *filesystem,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (options != NULL)
|
||||
+ {
|
||||
+ g_variant_lookup (options,
|
||||
+ "as-user",
|
||||
+ "&s",
|
||||
+ &opt_as_user);
|
||||
+ }
|
||||
+
|
||||
block = udisks_object_peek_block (object);
|
||||
daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
|
||||
state = udisks_daemon_get_state (daemon);
|
||||
@@ -862,22 +871,35 @@ handle_mount (UDisksFilesystem *filesystem,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!udisks_daemon_util_get_caller_uid_sync (daemon,
|
||||
- invocation,
|
||||
- NULL /* GCancellable */,
|
||||
- &caller_uid,
|
||||
- &error))
|
||||
+ if (opt_as_user)
|
||||
{
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- g_clear_error (&error);
|
||||
- goto out;
|
||||
+ if (!udisks_daemon_util_get_user_info_by_name (opt_as_user, &caller_uid, &caller_gid, &error))
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ g_clear_error (&error);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ caller_user_name = g_strdup (opt_as_user);
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ if (!udisks_daemon_util_get_caller_uid_sync (daemon,
|
||||
+ invocation,
|
||||
+ NULL /* GCancellable */,
|
||||
+ &caller_uid,
|
||||
+ &error))
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ g_clear_error (&error);
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- if (!udisks_daemon_util_get_user_info (caller_uid, &caller_gid, &caller_user_name, &error))
|
||||
- {
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- g_clear_error (&error);
|
||||
- goto out;
|
||||
+ if (!udisks_daemon_util_get_user_info (caller_uid, &caller_gid, &caller_user_name, &error))
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ g_clear_error (&error);
|
||||
+ goto out;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (system_managed)
|
||||
@@ -896,7 +918,11 @@ handle_mount (UDisksFilesystem *filesystem,
|
||||
* will be replaced by the name of the drive/device in question
|
||||
*/
|
||||
message = N_("Authentication is required to mount $(drive)");
|
||||
- if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
|
||||
+ if (opt_as_user != NULL)
|
||||
+ {
|
||||
+ action_id = "org.freedesktop.udisks2.filesystem-mount-other-user";
|
||||
+ }
|
||||
+ else if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
|
||||
{
|
||||
if (udisks_block_get_hint_system (block))
|
||||
{
|
||||
@@ -1078,7 +1104,11 @@ handle_mount (UDisksFilesystem *filesystem,
|
||||
* will be replaced by the name of the drive/device in question
|
||||
*/
|
||||
message = N_("Authentication is required to mount $(drive)");
|
||||
- if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
|
||||
+ if (opt_as_user != NULL)
|
||||
+ {
|
||||
+ action_id = "org.freedesktop.udisks2.filesystem-mount-other-user";
|
||||
+ }
|
||||
+ else if (!udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
|
||||
{
|
||||
if (udisks_block_get_hint_system (block))
|
||||
{
|
||||
--
|
||||
2.30.2
|
||||
|
99
spec_files/udisks2/sanitize-mount-point.patch
Normal file
99
spec_files/udisks2/sanitize-mount-point.patch
Normal file
@ -0,0 +1,99 @@
|
||||
diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c
|
||||
index f7c9975..97506e6 100644
|
||||
--- a/src/udiskslinuxfilesystem.c
|
||||
+++ b/src/udiskslinuxfilesystem.c
|
||||
@@ -521,6 +521,40 @@ add_acl (const gchar *path,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+/*
|
||||
+ * Return mount_dir/label after sanitizing the label. Free with g_free().
|
||||
+ */
|
||||
+static gchar *
|
||||
+sanitize_mount_point (const gchar *mount_dir,
|
||||
+ const gchar *label)
|
||||
+{
|
||||
+ gchar *s, *p;
|
||||
+ GString *str = g_string_new (NULL);
|
||||
+ g_string_append_printf (str, "%s/", mount_dir);
|
||||
+ s = ensure_utf8 (label);
|
||||
+ for (p = s; *p != '\0'; p = g_utf8_next_char (p))
|
||||
+ {
|
||||
+ gchar c = *p;
|
||||
+ if ((guchar) c < 128)
|
||||
+ {
|
||||
+ if (!g_ascii_isprint (c) || c == '/' || c == '"' || c == '\'' || c == '\\')
|
||||
+ g_string_append_c (str, '_');
|
||||
+ else
|
||||
+ g_string_append_c (str, c);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ gunichar uc = g_utf8_get_char (p);
|
||||
+ if (!g_unichar_isprint (uc))
|
||||
+ g_string_append_c (str, '_');
|
||||
+ else
|
||||
+ g_string_append_unichar (str, uc);
|
||||
+ }
|
||||
+ }
|
||||
+ g_free (s);
|
||||
+ return g_string_free (str, FALSE);
|
||||
+}
|
||||
|
||||
/*
|
||||
* calculate_mount_point: <internal>
|
||||
@@ -555,8 +589,6 @@ calculate_mount_point (UDisksDaemon *daemon,
|
||||
gchar *mount_dir = NULL;
|
||||
gchar *mount_point = NULL;
|
||||
gchar *orig_mount_point;
|
||||
- GString *str;
|
||||
- gchar *s;
|
||||
guint n;
|
||||
|
||||
label = NULL;
|
||||
@@ -639,42 +671,13 @@ calculate_mount_point (UDisksDaemon *daemon,
|
||||
*persistent = TRUE;
|
||||
}
|
||||
|
||||
- /* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains
|
||||
- * the byte 0x2F if it's for the '/' character (U+002F SOLIDUS).
|
||||
- *
|
||||
- * See http://en.wikipedia.org/wiki/UTF-8 for details.
|
||||
- */
|
||||
if (label != NULL && strlen (label) > 0)
|
||||
{
|
||||
- str = g_string_new (NULL);
|
||||
- g_string_append_printf (str, "%s/", mount_dir);
|
||||
- s = ensure_utf8 (label);
|
||||
- for (n = 0; s[n] != '\0'; n++)
|
||||
- {
|
||||
- gint c = s[n];
|
||||
- if (c == '/')
|
||||
- g_string_append_c (str, '_');
|
||||
- else
|
||||
- g_string_append_c (str, c);
|
||||
- }
|
||||
- mount_point = g_string_free (str, FALSE);
|
||||
- g_free (s);
|
||||
+ mount_point = sanitize_mount_point (mount_dir, label);
|
||||
}
|
||||
else if (uuid != NULL && strlen (uuid) > 0)
|
||||
{
|
||||
- str = g_string_new (NULL);
|
||||
- g_string_append_printf (str, "%s/", mount_dir);
|
||||
- s = ensure_utf8 (uuid);
|
||||
- for (n = 0; s[n] != '\0'; n++)
|
||||
- {
|
||||
- gint c = s[n];
|
||||
- if (c == '/')
|
||||
- g_string_append_c (str, '_');
|
||||
- else
|
||||
- g_string_append_c (str, c);
|
||||
- }
|
||||
- mount_point = g_string_free (str, FALSE);
|
||||
- g_free (s);
|
||||
+ mount_point = sanitize_mount_point (mount_dir, uuid);
|
||||
}
|
||||
else
|
||||
{
|
@ -81,7 +81,8 @@ Patch19: udisks-2.10.0-lvm2_vgcreate_uevent_sync.patch
|
||||
Patch20: udisks-2.9.4-tests_job_unstable.patch
|
||||
|
||||
# Bazzite
|
||||
Patch21: https://gitlab.com/evlaV/jupiter-PKGBUILD/-/raw/master/udisks2/mount-other-user.patch
|
||||
Patch21: sanitize-mount-point.patch
|
||||
Patch22: mount-other-user.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: glib2-devel >= %{glib2_version}
|
||||
|
Loading…
x
Reference in New Issue
Block a user