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