|
|
b677e7 |
From 996f88461c45e8620c5a8a0c958dc133bd02c50e Mon Sep 17 00:00:00 2001
|
|
|
b677e7 |
From: Jakob Unterwurzacher <jakobunt@gmail.com>
|
|
|
b677e7 |
Date: Mon, 30 Nov 2020 10:27:48 +0100
|
|
|
b677e7 |
Subject: [PATCH] mount-util: bind_remount: avoid calling statvfs
|
|
|
b677e7 |
|
|
|
b677e7 |
The commit
|
|
|
b677e7 |
"util: Do not clear parent mount flags when setting up namespaces"
|
|
|
b677e7 |
introduced a statvfs call read the flags of the original mount
|
|
|
b677e7 |
and have them applied to the bind mount.
|
|
|
b677e7 |
|
|
|
b677e7 |
This has two problems:
|
|
|
b677e7 |
|
|
|
b677e7 |
(1) The mount flags returned by statvfs(2) do not match the flags
|
|
|
b677e7 |
accepted by mount(2). For example, the value 4096 means ST_RELATIME
|
|
|
b677e7 |
when returned by statvfs(2), but means MS_BIND when passed to mount(2).
|
|
|
b677e7 |
|
|
|
b677e7 |
(2) A call to statvfs blocks indefinitely when ran against a disconnected
|
|
|
b677e7 |
network drive ( https://github.com/systemd/systemd/issues/12667 ).
|
|
|
b677e7 |
|
|
|
b677e7 |
We already use libmount to parse `/proc/self/mountinfo` but did not use the
|
|
|
b677e7 |
mount flag information from there. This patch changes that to use the mount
|
|
|
b677e7 |
flags parsed by libmount instead of calling statvfs. Only if getting the
|
|
|
b677e7 |
flags through libmount fails we call statvfs.
|
|
|
b677e7 |
|
|
|
b677e7 |
Fixes https://github.com/systemd/systemd/issues/12667
|
|
|
b677e7 |
|
|
|
b677e7 |
(cherry picked from commit d34a40082db3ffca8de66bfa4df50951101bdae5)
|
|
|
b677e7 |
|
|
|
b677e7 |
Resolves: #1885143
|
|
|
b677e7 |
---
|
|
|
b677e7 |
src/basic/mount-util.c | 31 +++++++++++++++++++++++++++----
|
|
|
b677e7 |
1 file changed, 27 insertions(+), 4 deletions(-)
|
|
|
b677e7 |
|
|
|
b677e7 |
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
|
|
|
b677e7 |
index bac1a25cc8..2cf98eaa84 100644
|
|
|
b677e7 |
--- a/src/basic/mount-util.c
|
|
|
b677e7 |
+++ b/src/basic/mount-util.c
|
|
|
b677e7 |
@@ -364,11 +364,34 @@ int umount_recursive(const char *prefix, int flags) {
|
|
|
b677e7 |
return r ? r : n;
|
|
|
b677e7 |
}
|
|
|
b677e7 |
|
|
|
b677e7 |
-static int get_mount_flags(const char *path, unsigned long *flags) {
|
|
|
b677e7 |
- struct statvfs buf;
|
|
|
b677e7 |
+/* Get the mount flags for the mountpoint at "path" from "table" */
|
|
|
b677e7 |
+static int get_mount_flags(const char *path, unsigned long *flags, struct libmnt_table *table) {
|
|
|
b677e7 |
+ struct statvfs buf = {};
|
|
|
b677e7 |
+ struct libmnt_fs *fs = NULL;
|
|
|
b677e7 |
+ const char *opts = NULL;
|
|
|
b677e7 |
+ int r = 0;
|
|
|
b677e7 |
+
|
|
|
b677e7 |
+ fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
|
|
|
b677e7 |
+ if (fs == NULL) {
|
|
|
b677e7 |
+ log_warning("Could not find '%s' in mount table", path);
|
|
|
b677e7 |
+ goto fallback;
|
|
|
b677e7 |
+ }
|
|
|
b677e7 |
+
|
|
|
b677e7 |
+ opts = mnt_fs_get_vfs_options(fs);
|
|
|
b677e7 |
+ r = mnt_optstr_get_flags(opts, flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
|
|
|
b677e7 |
+ if (r != 0) {
|
|
|
b677e7 |
+ log_warning_errno(r, "Could not get flags for '%s': %m", path);
|
|
|
b677e7 |
+ goto fallback;
|
|
|
b677e7 |
+ }
|
|
|
b677e7 |
|
|
|
b677e7 |
+ /* relatime is default and trying to set it in an unprivileged container causes EPERM */
|
|
|
b677e7 |
+ *flags &= ~MS_RELATIME;
|
|
|
b677e7 |
+ return 0;
|
|
|
b677e7 |
+
|
|
|
b677e7 |
+fallback:
|
|
|
b677e7 |
if (statvfs(path, &buf) < 0)
|
|
|
b677e7 |
return -errno;
|
|
|
b677e7 |
+
|
|
|
b677e7 |
*flags = buf.f_flag;
|
|
|
b677e7 |
return 0;
|
|
|
b677e7 |
}
|
|
|
b677e7 |
@@ -501,7 +524,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
|
|
|
b677e7 |
return -errno;
|
|
|
b677e7 |
|
|
|
b677e7 |
orig_flags = 0;
|
|
|
b677e7 |
- (void) get_mount_flags(cleaned, &orig_flags);
|
|
|
b677e7 |
+ (void) get_mount_flags(cleaned, &orig_flags, table);
|
|
|
b677e7 |
orig_flags &= ~MS_RDONLY;
|
|
|
b677e7 |
|
|
|
b677e7 |
if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
|
|
|
b677e7 |
@@ -535,7 +558,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
|
|
|
b677e7 |
|
|
|
b677e7 |
/* Try to reuse the original flag set */
|
|
|
b677e7 |
orig_flags = 0;
|
|
|
b677e7 |
- (void) get_mount_flags(x, &orig_flags);
|
|
|
b677e7 |
+ (void) get_mount_flags(x, &orig_flags, table);
|
|
|
b677e7 |
orig_flags &= ~MS_RDONLY;
|
|
|
b677e7 |
|
|
|
b677e7 |
if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
|