summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-20 23:12:53 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-25 10:41:26 +0200
commit874052c5014e774a9c9ca86149c724a7440d7094 (patch)
treee42232d9135594489e3c0c664c03f9ee1ad7add9 /src/shared
parentmount-util: use modern mount_setattr() syscall for bind_remount_one_with_moun... (diff)
downloadsystemd-874052c5014e774a9c9ca86149c724a7440d7094.tar.xz
systemd-874052c5014e774a9c9ca86149c724a7440d7094.zip
mount-util: port over bind_remount_recursive_with_mountinfo() to mount_setattr()
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/mount-util.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 25dde7b0e2..2dad667126 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -175,6 +175,30 @@ int bind_remount_recursive_with_mountinfo(
assert(prefix);
assert(proc_self_mountinfo);
+ if ((flags_mask & ~MS_CONVERTIBLE_FLAGS) == 0 && strv_isempty(deny_list) && !skip_mount_set_attr) {
+ /* Let's take a shortcut for all the flags we know how to convert into mount_setattr() flags */
+
+ if (mount_setattr(AT_FDCWD, prefix, AT_SYMLINK_NOFOLLOW|AT_RECURSIVE,
+ &(struct mount_attr) {
+ .attr_set = ms_flags_to_mount_attr(new_flags & flags_mask),
+ .attr_clr = ms_flags_to_mount_attr(~new_flags & flags_mask),
+ }, MOUNT_ATTR_SIZE_VER0) < 0) {
+
+ log_debug_errno(errno, "mount_setattr() failed, falling back to classic remounting: %m");
+
+ /* We fall through to classic behaviour if not supported (i.e. kernel < 5.12). We
+ * also do this for all other kinds of errors since they are so many different, and
+ * mount_setattr() has no graceful mode where it continues despite seeing errors one
+ * some mounts, but we want that. Moreover mount_setattr() only works on the mount
+ * point inode itself, not a non-mount point inode, and we want to support arbitrary
+ * prefixes here. */
+
+ if (ERRNO_IS_NOT_SUPPORTED(errno)) /* if not supported, then don't bother at all anymore */
+ skip_mount_set_attr = true;
+ } else
+ return 0; /* Nice, this worked! */
+ }
+
/* Recursively remount a directory (and all its submounts) with desired flags (MS_READONLY,
* MS_NOSUID, MS_NOEXEC). If the directory is already mounted, we reuse the mount and simply mark it
* MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write operation), ditto for other flags. If it