From: Lennart Poettering Date: Wed, 20 Oct 2021 21:12:53 +0000 (+0200) Subject: mount-util: port over bind_remount_recursive_with_mountinfo() to mount_setattr() X-Git-Tag: v250-rc1~435^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=874052c5014e774a9c9ca86149c724a7440d7094;p=thirdparty%2Fsystemd.git mount-util: port over bind_remount_recursive_with_mountinfo() to mount_setattr() --- diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 25dde7b0e28..2dad667126f 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 diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 978fd45005d..fdf2a249ed2 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -169,7 +169,7 @@ static void test_bind_remount_recursive(void) { assert_se(!FLAGS_SET(svfs.f_flag, ST_RDONLY)); /* Now mark the path we currently run for read-only */ - assert_se(bind_remount_recursive(p, MS_RDONLY, MS_RDONLY, STRV_MAKE("/sys/kernel")) >= 0); + assert_se(bind_remount_recursive(p, MS_RDONLY, MS_RDONLY, path_equal(p, "/sys") ? STRV_MAKE("/sys/kernel") : NULL) >= 0); /* Ensure that this worked on the top-level */ assert_se(statvfs(p, &svfs) >= 0);