libmount: add support for "bind,ro"

Now it's necessary t 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.

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2015-08-17 11:54:26 +02:00
parent 5b7be9900a
commit 9ac77b8a78
3 changed files with 67 additions and 20 deletions

View File

@ -9,6 +9,10 @@ new default unifies unshare behavior and makes it independent of distribution
default. The unshare supports persistent namespaces too (no process has to run
to keep namespace in existence).
The command mount(8) supports read-only binds in one step by the options
"bind,ro" (command line or fstab). This feature is implemented by additional
remount mount(2) syscall and it is not atomic.
The commands fdisk and sfdisk can be compiled with GNU readline support to
improve their line-editing functionality.

View File

@ -63,6 +63,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)
return 0;
}
/*
* 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, ul_debugobj(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;
}
#if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK)
struct libmnt_optname {
const char *name;
@ -214,6 +253,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;
@ -731,7 +777,7 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
-cxt->syscall_status));
return -cxt->syscall_status;
}
DBG(CXT, ul_debugobj(cxt, "mount(2) success"));
DBG(CXT, ul_debugobj(cxt, " success"));
cxt->syscall_status = 0;
/*

View File

@ -362,28 +362,25 @@ a second place by using:
.RE
Note that the filesystem mount options will remain the same as those
on the original mount point, and cannot be changed by passing the
on the original mount point.
.BR mount(8)
since v2.27 allow to change the options by passing the
.B \-o
option along with
.BR \-\-bind / \-\-rbind .
The mount options can be
changed by a separate remount command, for example:
.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 the behavior of the remount operation depends on the /etc/mtab file.
The first command stores the 'bind' flag in 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 \fBmount\fR(8) does not read /etc/mtab), then you have to use
the 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
@ -394,14 +391,14 @@ the bind flag (or option) for the remount command too. For example:
.I olddir newdir
.RE
Note that
.B remount,ro,bind
will create a read-only mountpoint (VFS entry), but the original filesystem
superblock will still be writable, meaning 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 b \fB -o rbind,ro\fR).
.RE
.B The move operation.