File 0001-Filesystem-ignore-fstab-entry-if-another-device-is-m.patch of Package udisks2.25781
From 3997c10064a5d526b8d49d72bcbd3720ca793a5a Mon Sep 17 00:00:00 2001
From: Will Thompson <wjt@endlessm.com>
Date: Sun, 12 May 2019 08:37:21 -0700
Subject: [PATCH] Filesystem: ignore fstab entry if another device is mounted
there
On Endless OS, all systems have the following /etc/fstab:
LABEL=ostree / ext4 errors=remount-ro 0 0
If you insert a removable device containing a filesystem with the label
'ostree', then asks UDisks to mount it, it will attempt to mount it over
/. If the filesystem is not of type ext4, this will fail; if it is, this
will succeed, with potentially disastrous results.
There is already a check in is_in_fstab() which constructs the path to
the /dev/disk/by-label/$LABEL symlink and compares it to the device
being mounted. However, in this scenario that comparison succeeds: the
symlink is updated when the new device is detected.
To prevent this, use UDisksMountMonitor to look up the mount point
specified in fstab (using a new get_mount_for_path accessor); if an
existing mount is found, and it is a different device to the one being
(un)mounted, ignore the fstab entry.
(cherry picked from commit e86ea628177c3ea67525175f73a143e15ea74d67)
---
src/udiskslinuxfilesystem.c | 43 ++++++++++++++++++++++++-------------
src/udisksmountmonitor.c | 33 ++++++++++++++++++++++++++++
src/udisksmountmonitor.h | 2 ++
3 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c
index f243046e..9ca70443 100644
--- a/src/udiskslinuxfilesystem.c
+++ b/src/udiskslinuxfilesystem.c
@@ -1025,11 +1025,13 @@ has_option (const gchar *options,
}
static gboolean
-is_in_fstab (UDisksBlock *block,
- const gchar *fstab_path,
- gchar **out_mount_point,
- gchar **out_mount_options)
+is_in_fstab (UDisksDaemon *daemon,
+ UDisksBlock *block,
+ const gchar *fstab_path,
+ gchar **out_mount_point,
+ gchar **out_mount_options)
{
+ UDisksMountMonitor *mount_monitor = udisks_daemon_get_mount_monitor (daemon);
gboolean ret;
FILE *f;
char buf[8192];
@@ -1083,11 +1085,21 @@ is_in_fstab (UDisksBlock *block,
if (udisks_block_get_device_number (block) == sb.st_rdev)
{
- ret = TRUE;
- if (out_mount_point != NULL)
- *out_mount_point = g_strdup (m->mnt_dir);
- if (out_mount_options != NULL)
- *out_mount_options = g_strdup (m->mnt_opts);
+ /* If this block device is found in fstab, but something else is already
+ * mounted on that mount point, ignore the fstab entry.
+ */
+ UDisksMount *mount = udisks_mount_monitor_get_mount_for_path (mount_monitor,
+ m->mnt_dir);
+ if (mount == NULL || sb.st_rdev == udisks_mount_get_dev (mount))
+ {
+ ret = TRUE;
+ if (out_mount_point != NULL)
+ *out_mount_point = g_strdup (m->mnt_dir);
+ if (out_mount_options != NULL)
+ *out_mount_options = g_strdup (m->mnt_opts);
+ }
+
+ g_clear_object (&mount);
}
continue_loop:
@@ -1106,16 +1118,17 @@ is_in_fstab (UDisksBlock *block,
* TODO: check if systemd has a specific "unit" for the device
*/
static gboolean
-is_system_managed (UDisksBlock *block,
- gchar **out_mount_point,
- gchar **out_mount_options)
+is_system_managed (UDisksDaemon *daemon,
+ UDisksBlock *block,
+ gchar **out_mount_point,
+ gchar **out_mount_options)
{
gboolean ret;
ret = TRUE;
/* First, check /etc/fstab */
- if (is_in_fstab (block, "/etc/fstab", out_mount_point, out_mount_options))
+ if (is_in_fstab (daemon, block, "/etc/fstab", out_mount_point, out_mount_options))
goto out;
ret = FALSE;
@@ -1184,7 +1197,7 @@ handle_mount (UDisksFilesystem *filesystem,
state = udisks_daemon_get_state (daemon);
/* check if mount point is managed by e.g. /etc/fstab or similar */
- if (is_system_managed (block, &mount_point_to_use, &fstab_mount_options))
+ if (is_system_managed (daemon, block, &mount_point_to_use, &fstab_mount_options))
{
system_managed = TRUE;
}
@@ -1617,7 +1630,7 @@ handle_unmount (UDisksFilesystem *filesystem,
}
/* check if mount point is managed by e.g. /etc/fstab or similar */
- if (is_system_managed (block, &mount_point, &fstab_mount_options))
+ if (is_system_managed (daemon, block, &mount_point, &fstab_mount_options))
{
system_managed = TRUE;
}
diff --git a/src/udisksmountmonitor.c b/src/udisksmountmonitor.c
index e7097faf..bc7abd57 100644
--- a/src/udisksmountmonitor.c
+++ b/src/udisksmountmonitor.c
@@ -704,3 +704,36 @@ udisks_mount_monitor_is_dev_in_use (UDisksMountMonitor *monitor,
out:
return ret;
}
+
+/**
+ * udisks_mount_monitor_get_mount_for_path:
+ * @monitor: A #UDisksMountMonitor.
+ * @mount_path: A filesystem path on which a device may be mounted.
+ *
+ * Gets the #UDisksMount mounted at @mount_path, if any.
+ *
+ * Returns: (transfer full) (nullable): the #UDisksMount (of type
+ * #UDISKS_MOUNT_TYPE_FILESYSTEM) mounted at @mount_path, or %NULL if nothing
+ * is mounted there.
+ */
+UDisksMount *
+udisks_mount_monitor_get_mount_for_path (UDisksMountMonitor *monitor,
+ const gchar *mount_path)
+{
+ GList *l;
+
+ g_return_val_if_fail (UDISKS_IS_MOUNT_MONITOR (monitor), NULL);
+ g_return_val_if_fail (mount_path != NULL, NULL);
+
+ udisks_mount_monitor_ensure (monitor);
+ for (l = monitor->mounts; l != NULL; l = l->next)
+ {
+ UDisksMount *mount = UDISKS_MOUNT (l->data);
+
+ if (udisks_mount_get_mount_type (mount) == UDISKS_MOUNT_TYPE_FILESYSTEM &&
+ g_strcmp0 (udisks_mount_get_mount_path (mount), mount_path) == 0)
+ return g_object_ref (mount);
+ }
+
+ return NULL;
+}
diff --git a/src/udisksmountmonitor.h b/src/udisksmountmonitor.h
index c30cf318..5bab112e 100644
--- a/src/udisksmountmonitor.h
+++ b/src/udisksmountmonitor.h
@@ -36,6 +36,8 @@ GList *udisks_mount_monitor_get_mounts_for_dev (UDisksMountMonitor
gboolean udisks_mount_monitor_is_dev_in_use (UDisksMountMonitor *monitor,
dev_t dev,
UDisksMountType *out_type);
+UDisksMount *udisks_mount_monitor_get_mount_for_path (UDisksMountMonitor *monitor,
+ const gchar *mount_path);
G_END_DECLS
--
2.37.2