summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-03-24 14:16:45 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-05-07 11:58:41 +0200
commitc2e7941d914968d15bfc2ced889f9e76ae875f2a (patch)
tree39509e4f0e5e1d65ad53a957d0912159bf5609e5
parentbad107f1518452c725f0142bb223f77acf1a62b5 (diff)
downloadsystemd-c2e7941d914968d15bfc2ced889f9e76ae875f2a.tar.gz
mount-util: fold what we need from get_mount_flags() bind_remount_one_with_mountinfo()
And get rid of get_mount_flags() altogether. (This drops the statvfs() fallback that get_mount_flags() did. That fallback was incomplete however, and mostly hid errors. Our primary avenue to get mount flags is /proc/self/mountinfo and we should trust it, and fix bugs we might encounter with it, but not tape over it. Dropping the fallback is relevant in particular as it actually returned mount flags for any path, not just mount points, which was very icky.) (cherry picked from commit 2c5ff8ea76d8c3c9944567ae97f498925dfcd443)
-rw-r--r--src/shared/mount-util.c80
1 files changed, 14 insertions, 66 deletions
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 381fece872..ab2f62c32f 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -131,68 +131,6 @@ int umount_recursive(const char *prefix, int flags) {
return n;
}
-static int get_mount_flags(
- struct libmnt_table *table,
- const char *path,
- unsigned long *ret) {
-
- _cleanup_close_ int fd = -1;
- struct libmnt_fs *fs;
- struct statvfs buf;
- const char *opts;
- int r;
-
- /* Get the mount flags for the mountpoint at "path" from "table". We have a fallback using statvfs()
- * in place (which provides us with mostly the same info), but it's just a fallback, since using it
- * means triggering autofs or NFS mounts, which we'd rather avoid needlessly.
- *
- * This generally doesn't follow symlinks. */
-
- fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
- if (!fs) {
- log_debug("Could not find '%s' in mount table, ignoring.", path);
- goto fallback;
- }
-
- opts = mnt_fs_get_vfs_options(fs);
- if (!opts) {
- *ret = 0;
- return 0;
- }
-
- r = mnt_optstr_get_flags(opts, ret, mnt_get_builtin_optmap(MNT_LINUX_MAP));
- if (r != 0) {
- log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
- goto fallback;
- }
-
- /* MS_RELATIME is default and trying to set it in an unprivileged container causes EPERM */
- *ret &= ~MS_RELATIME;
- return 0;
-
-fallback:
- fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- if (fstatvfs(fd, &buf) < 0)
- return -errno;
-
- /* The statvfs() flags and the mount flags mostly have the same values, but for some cases do
- * not. Hence map the flags manually. (Strictly speaking, ST_RELATIME/MS_RELATIME is the most
- * prominent one that doesn't match, but that's the one we mask away anyway, see above.) */
-
- *ret =
- FLAGS_SET(buf.f_flag, ST_RDONLY) * MS_RDONLY |
- FLAGS_SET(buf.f_flag, ST_NODEV) * MS_NODEV |
- FLAGS_SET(buf.f_flag, ST_NOEXEC) * MS_NOEXEC |
- FLAGS_SET(buf.f_flag, ST_NOSUID) * MS_NOSUID |
- FLAGS_SET(buf.f_flag, ST_NOATIME) * MS_NOATIME |
- FLAGS_SET(buf.f_flag, ST_NODIRATIME) * MS_NODIRATIME;
-
- return 0;
-}
-
/* Use this function only if you do not have direct access to /proc/self/mountinfo but the caller can open it
* for you. This is the case when /proc is masked or not mounted. Otherwise, use bind_remount_recursive. */
int bind_remount_recursive_with_mountinfo(
@@ -419,7 +357,9 @@ int bind_remount_one_with_mountinfo(
FILE *proc_self_mountinfo) {
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
- unsigned long orig_flags = 0;
+ unsigned long flags = 0;
+ struct libmnt_fs *fs;
+ const char *opts;
int r;
assert(path);
@@ -435,10 +375,18 @@ int bind_remount_one_with_mountinfo(
if (r < 0)
return r;
- /* Try to reuse the original flag set */
- (void) get_mount_flags(table, path, &orig_flags);
+ fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
+ if (!fs)
+ return -EINVAL; /* Not a mount point we recognize */
+
+ opts = mnt_fs_get_vfs_options(fs);
+ if (opts) {
+ r = mnt_optstr_get_flags(opts, &flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
+ if (r < 0)
+ log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
+ }
- r = mount_nofollow(NULL, path, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL);
+ r = mount_nofollow(NULL, path, NULL, ((flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags) & ~MS_RELATIME, NULL);
if (r < 0)
return r;