File 0001-Filesystem-ignore-fstab-entry-if-another-device-is-m.patch of Package udisks2.40356
From 0ed55973f8ec38be736bb524d4c8c9f8282679e5 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 | 33 +++++++++++++++++++++++----------
src/udisksmountmonitor.c | 33 +++++++++++++++++++++++++++++++++
src/udisksmountmonitor.h | 2 ++
3 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c
index 8d1bff42..753273f8 100644
--- a/src/udiskslinuxfilesystem.c
+++ b/src/udiskslinuxfilesystem.c
@@ -1112,11 +1112,13 @@ has_option (const gchar *options,
}
static gboolean
-is_in_fstab (UDisksBlock *block,
+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];
@@ -1178,11 +1180,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:
@@ -1201,7 +1213,8 @@ is_in_fstab (UDisksBlock *block,
* TODO: check if systemd has a specific "unit" for the device
*/
static gboolean
-is_system_managed (UDisksBlock *block,
+is_system_managed (UDisksDaemon *daemon,
+ UDisksBlock *block,
gchar **out_mount_point,
gchar **out_mount_options)
{
@@ -1210,7 +1223,7 @@ is_system_managed (UDisksBlock *block,
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;
@@ -1325,7 +1338,7 @@ handle_mount (UDisksFilesystem *filesystem,
device = udisks_block_dup_device (block);
/* 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;
}
@@ -1739,7 +1752,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 286071a8..a927838d 100644
--- a/src/udisksmountmonitor.c
+++ b/src/udisksmountmonitor.c
@@ -724,3 +724,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