[3/4] mount: apply superblock flags from the userns daemon

Submitted by Andrei Vagin on Oct. 26, 2016, 8:55 p.m.

Details

Message ID 1477515324-16187-4-git-send-email-avagin@openvz.org
State Superseded
Series "Fix a few issues to dump/restore Docker containers with userns"
Headers show

Commit Message

Andrei Vagin Oct. 26, 2016, 8:55 p.m.
From: Andrei Vagin <avagin@virtuozzo.com>

Superblock flags can be changed only an owner of the global CAP_SYS_ADMIN.

But it is posible to mount tmpfs with any flags.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/mount.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/mount.c b/criu/mount.c
index 6ed70ad..598c3b6 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -1690,6 +1690,27 @@  static char *mnt_fsname(struct mount_info *mi)
 	return mi->fstype->name;
 }
 
+static int apply_sb_flags(void *args, int fd, pid_t pid)
+{
+	int rst = -1, err = -1;
+	long flags = *(int *) args;
+	char path[PSFDS];
+
+	snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+	if (pid != getpid() && switch_ns(pid, &mnt_ns_desc, &rst))
+		return -1;
+
+	err = mount(NULL, path, NULL, MS_REMOUNT | flags, NULL);
+	if (err)
+		pr_perror("Unable to remount %s", path);
+
+	if (rst >= 0 &&	restore_ns(rst, &mnt_ns_desc))
+		return -1;
+
+	return err;
+}
+
 static int do_new_mount(struct mount_info *mi)
 {
 	unsigned long sflags = mi->sb_flags;
@@ -1730,9 +1751,23 @@  static int do_new_mount(struct mount_info *mi)
 	}
 
 	if (!mi->is_ns_root && !mi->external && remount_ro) {
-				     MS_REMOUNT | MS_RDONLY, NULL)) {
-		pr_perror("Unable to apply mount options");
-		return -1;
+		int fd;
+
+		fd = open(mi->mountpoint, O_PATH);
+		if (fd < 0) {
+			pr_perror("Unable to open %s\n", mi->mountpoint);
+			return -1;
+		}
+
+		sflags |= MS_RDONLY;
+		if (userns_call(apply_sb_flags, 0,
+				&sflags, sizeof(int), fd)) {
+			pr_perror("Unable to apply mount falgs %d for %s",
+						mi->sb_flags, mi->mountpoint);
+			close(fd);
+			return -1;
+		}
+		close(fd);
 	}
 
 	if (mflags && mount(NULL, mi->mountpoint, NULL,