cdown / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone
531551
From 2218dc0d130bb72809e2d8b26a36402bf6293727 Mon Sep 17 00:00:00 2001
531551
From: Karel Zak <kzak@redhat.com>
531551
Date: Mon, 17 Aug 2015 11:54:26 +0200
531551
Subject: [PATCH 84/86] libmount: add support for "bind,ro"
531551
531551
Now it's necessary to use two mount(8) calls to create a read-only
531551
mount:
531551
531551
  mount /foo /bar -o bind
531551
  mount /bar -o remount,ro,bind
531551
531551
This patch allows to specify "bind,ro" and the remount is done
531551
automatically by libmount by additional mount(2) syscall. It's not
531551
atomic of course.
531551
531551
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1281839
531551
Signed-off-by: Karel Zak <kzak@redhat.com>
531551
---
531551
 libmount/src/context_mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
531551
 sys-utils/mount.8            | 37 ++++++++++++++++++-----------------
531551
 2 files changed, 65 insertions(+), 18 deletions(-)
531551
531551
diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
531551
index d6691eb..4df2646 100644
531551
--- a/libmount/src/context_mount.c
531551
+++ b/libmount/src/context_mount.c
531551
@@ -62,6 +62,10 @@ static int mnt_context_append_additional_mount(struct libmnt_context *cxt,
531551
 	return 0;
531551
 }
531551
 
531551
+/*
531551
+ * add additional mount(2) syscall requests when necessary to set propagation flags
531551
+ * after regular mount(2).
531551
+ */
531551
 static int init_propagation(struct libmnt_context *cxt)
531551
 {
531551
 	char *name;
531551
@@ -102,6 +106,41 @@ static int init_propagation(struct libmnt_context *cxt)
531551
 }
531551
 
531551
 /*
531551
+ * add additional mount(2) syscall request to implement "ro,bind", the first regular
531551
+ * mount(2) is the "bind" operation, the second is "remount,ro,bind" call.
531551
+ *
531551
+ * Note that we don't remove "ro" from the first syscall (kernel silently
531551
+ * ignores this flags for bind operation) -- maybe one day kernel will support
531551
+ * read-only binds in one step and then all will be done by the firts mount(2) and the
531551
+ * second remount will be noop...
531551
+ */
531551
+static int init_robind(struct libmnt_context *cxt)
531551
+{
531551
+	struct libmnt_addmount *ad;
531551
+	int rc;
531551
+
531551
+	assert(cxt);
531551
+	assert(cxt->mountflags & MS_BIND);
531551
+	assert(cxt->mountflags & MS_RDONLY);
531551
+	assert(!(cxt->mountflags & MS_REMOUNT));
531551
+
531551
+	DBG(CXT, mnt_debug_h(cxt, "mount: initialize additional ro,bind mount"));
531551
+
531551
+	ad = mnt_new_addmount();
531551
+	if (!ad)
531551
+		return -ENOMEM;
531551
+
531551
+	ad->mountflags = MS_REMOUNT | MS_BIND | MS_RDONLY;
531551
+	if (cxt->mountflags & MS_REC)
531551
+		ad->mountflags |= MS_REC;
531551
+	rc = mnt_context_append_additional_mount(cxt, ad);
531551
+	if (rc)
531551
+		return rc;
531551
+
531551
+	return 0;
531551
+}
531551
+
531551
+/*
531551
  * this has to be called after mnt_context_evaluate_permissions()
531551
  */
531551
 static int fix_optstr(struct libmnt_context *cxt)
531551
@@ -174,6 +213,13 @@ static int fix_optstr(struct libmnt_context *cxt)
531551
 		if (rc)
531551
 			return rc;
531551
 	}
531551
+	if ((cxt->mountflags & MS_BIND)
531551
+	    && (cxt->mountflags & MS_RDONLY)
531551
+	    && !(cxt->mountflags & MS_REMOUNT)) {
531551
+		rc = init_robind(cxt);
531551
+		if (rc)
531551
+			return rc;
531551
+	}
531551
 
531551
 	next = fs->fs_optstr;
531551
 
531551
diff --git a/sys-utils/mount.8 b/sys-utils/mount.8
531551
index 3648870..49cb281 100644
531551
--- a/sys-utils/mount.8
531551
+++ b/sys-utils/mount.8
531551
@@ -388,25 +388,25 @@ or shortoption
531551
 .\" available since Linux 2.4.11.
531551
 
531551
 Note that the filesystem mount options will remain the same as those
531551
-on the original mount point, and cannot be changed by passing the -o
531551
-option along with --bind/--rbind. The mount options can be
531551
-changed by a separate remount command, for example:
531551
+on the original mount point.
531551
+
531551
+.BR mount(8)
531551
+since v2.27 (backported to RHEL7.3) allow to change the options by passing the
531551
+.B \-o
531551
+option along with
531551
+.BR \-\-bind
531551
+for example:
531551
 
531551
 .RS
531551
 .br
531551
-.B mount --bind
531551
-.I olddir newdir
531551
-.br
531551
-.B mount -o remount,ro
531551
-.I newdir
531551
+.B mount \-\-bind,ro foo foo
531551
 .RE
531551
 
531551
-Note that behavior of the remount operation depends on the /etc/mtab file. The
531551
-first command stores the 'bind' flag to the /etc/mtab file and the second
531551
-command reads the flag from the file.  If you have a system without the
531551
-/etc/mtab file or if you explicitly define source and target for the remount
531551
-command (then mount(8) does not read /etc/mtab), then you have to use bind flag
531551
-(or option) for the remount command too. For example:
531551
+This feature is not supported by Linux kernel and it is implemented in userspace
531551
+by additional remount mount(2) syscall. This solution is not atomic.
531551
+
531551
+The alternative (classic) way to create a read-only bind mount is to use remount
531551
+operation, for example:
531551
 
531551
 .RS
531551
 .br
531551
@@ -417,14 +417,15 @@ command (then mount(8) does not read /etc/mtab), then you have to use bind flag
531551
 .I olddir newdir
531551
 .RE
531551
 
531551
-Note that
531551
-.I remount,ro,bind
531551
-will create a read-only mountpoint (VFS entry), but the original filesystem suberblock
531551
-will be still writable, it means that the
531551
+Note that read-only bind will create a read-only mountpoint (VFS entry), but the
531551
+original filesystem superblock will still be writable, meaning that the
531551
 .I olddir
531551
 will be writable, but the
531551
 .I newdir
531551
 will be read-only.
531551
+
531551
+It's impossible to change mount options recursively
531551
+(for example with \fB -o rbind,ro\fR).
531551
 .RE
531551
 
531551
 .B The move operation.
531551
-- 
531551
2.7.4
531551