Skip to content

Commit 4359289

Browse files
committed
remount-fs: do not remount filesystem to match fstab if something different is mounted
As reported in ostreedev/ostree#3193, when the system has mounted a different file system on "/" than what is configured in /etc/fstab, we still try to execute "mount -o remount /", and that fails because the filesystem that is actually mounted doesn't know about the options relevant for the filesystem listed in /etc/fstab. I don't think it's useful to try to apply options from /etc/fstab if the file system type or device are different. In fact, it could be dangerous or destructive. If the user mounted something different than what the fstab specifies, no matter by what means, we should leave that mount point alone. If the filesystem is (potentially) multi-device, we only require the file system type to match.
1 parent ea99987 commit 4359289

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

src/remount-fs/remount-fs.c

+82-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "main-func.h"
1515
#include "mount-setup.h"
1616
#include "mount-util.h"
17+
#include "mountpoint-util.h"
1718
#include "path-util.h"
1819
#include "process-util.h"
1920
#include "signal-util.h"
@@ -69,11 +70,87 @@ static int do_remount(const char *path, bool force_rw, Hashmap **pids) {
6970
return track_pid(pids, path, pid);
7071
}
7172

73+
static int device_node_uuid(const char *path, sd_id128_t *ret_uuid) {
74+
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
75+
int r;
76+
77+
r = sd_device_new_from_devname(&device, path);
78+
if (r < 0)
79+
return log_warning_errno(r, "Failed to create device from %s: %m", path);
80+
81+
const char *uuid;
82+
r = sd_device_get_property_value(device, "ID_FS_UUID", &uuid);
83+
if (r < 0)
84+
return log_warning_errno(r, "Failed to get filesystem UUID for device %s: %m", path);
85+
86+
r = sd_id128_from_string(uuid, ret_uuid);
87+
if (r < 0)
88+
return log_warning_errno(r, "Failed to parse ID_FS_UUID '%s' for device %s: %m",
89+
uuid, path);
90+
return 0;
91+
}
92+
93+
static int mount_point_matches(const struct mntent *me) {
94+
_cleanup_free_ char *what = NULL, *where = NULL, *type = NULL;
95+
int r;
96+
97+
r = path_get_mount_info(ASSERT_PTR(me)->mnt_dir, &what, &where, &type, /* options= */ NULL);
98+
if (r < 0)
99+
return log_warning_errno(r, "Failed to acquire information about mount point %s: %m", me->mnt_dir);
100+
if (!path_equal(me->mnt_dir, where)) { /* We got the containing mount point */
101+
log_info("Mount point \"%s\" is not mounted.", me->mnt_dir);
102+
return false;
103+
}
104+
105+
if (!streq(type, me->mnt_type) && !streq(me->mnt_type, "auto")) {
106+
log_info("File system mounted at \"%s\" doesn't match fstab (type %s vs. %s), ignoring.",
107+
me->mnt_dir, type, me->mnt_type);
108+
return false;
109+
}
110+
111+
if (!fstype_is_blockdev_backed(type)) {
112+
log_debug("File system mounted at \"%s\" matches fstab.", me->mnt_dir);
113+
return true; /* Nothing more to check, the "device" is not important. */
114+
}
115+
116+
/* Figure out if the two paths point at the same device node */
117+
_cleanup_free_ char *node = fstab_node_to_udev_node(me->mnt_fsname);
118+
if (!node)
119+
return log_oom();
120+
121+
r = path_equal_or_inode_same_full(what, node, AT_NO_AUTOMOUNT);
122+
if (r < 0)
123+
return log_warning_errno(r, "Failed to determine if %s and %s for mount point \"%s\" are same: %m",
124+
what, node, me->mnt_dir);
125+
if (r == 0 || true) {
126+
/* Try to figure out if the file system identifier matches…
127+
* This way we cover multi-device file systems like btrfs or bcachefs. */
128+
sd_id128_t uuid_a, uuid_b;
129+
130+
r = device_node_uuid(what, &uuid_a);
131+
if (r < 0)
132+
return r;
133+
134+
r = device_node_uuid(node, &uuid_b);
135+
if (r < 0)
136+
return r;
137+
138+
r = sd_id128_equal(uuid_a, uuid_b);
139+
}
140+
141+
if (r > 0)
142+
log_debug("File system mounted at \"%s\" matches fstab.", me->mnt_dir);
143+
else
144+
log_info("File system mounted at \"%s\" doesn't match fstab (%s vs. %s), ignoring.",
145+
me->mnt_dir, what, me->mnt_fsname);
146+
return r;
147+
}
148+
72149
static int remount_by_fstab(Hashmap **ret_pids) {
73150
_cleanup_hashmap_free_ Hashmap *pids = NULL;
74151
_cleanup_endmntent_ FILE *f = NULL;
75152
bool has_root = false;
76-
struct mntent* me;
153+
struct mntent *me;
77154
int r;
78155

79156
assert(ret_pids);
@@ -95,6 +172,10 @@ static int remount_by_fstab(Hashmap **ret_pids) {
95172
!PATH_IN_SET(me->mnt_dir, "/", "/usr"))
96173
continue;
97174

175+
r = mount_point_matches(me);
176+
if (r <= 0)
177+
continue;
178+
98179
if (path_equal(me->mnt_dir, "/"))
99180
has_root = true;
100181

0 commit comments

Comments
 (0)