[lxc-devel] [PATCH RFC] do_mount_entry: add nexec, nosuid, nodev, rdonly flags if needed at remount

Stéphane Graber stgraber at ubuntu.com
Mon Aug 18 03:36:14 UTC 2014


On Mon, Aug 18, 2014 at 03:28:21AM +0000, Serge Hallyn wrote:
> See http://lkml.org/lkml/2014/8/13/746 and its history.  The kernel now refuses
> mounts if we don't add ro,nosuid,nodev,noexec flags if they were already there.
> 
> Also use the newly found info to skip remount if unneeded.  For background, if
> you want to create a read-only bind mount, then you must first mount(2) with
> MS_BIND to create the bind mount, then re-mount(2) again to get the new mount
> options to apply.  So if this wasn't a bind mount, or no new mount options were
> introduced, then we don't do the second mount(2).
> 
> null_endofword() and get_field() were not changed, only moved up in
> the file.
> 
> (Note, while I can start containers inside a privileged container with
> this patch, most of the lxc tests still fail with the kernel in question;
> Andy's patch seems to still be needed - a kernel with which is available
> at https://launchpad.net/~serge-hallyn/+archive/ubuntu/userns-natty
> ppa:serge-hallyn/userns-natty)
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  src/lxc/conf.c | 107 ++++++++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 80 insertions(+), 27 deletions(-)
> 
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 2b3aff1..01ace43 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -1927,10 +1927,74 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags,
>  	return 0;
>  }
>  
> +static void null_endofword(char *word)
> +{
> +	while (*word && *word != ' ' && *word != '\t')
> +		word++;
> +	*word = '\0';
> +}
> +
> +/*
> + * skip @nfields spaces in @src
> + */
> +static char *get_field(char *src, int nfields)
> +{
> +	char *p = src;
> +	int i;
> +
> +	for (i = 0; i < nfields; i++) {
> +		while (*p && *p != ' ' && *p != '\t')
> +			p++;
> +		if (!*p)
> +			break;
> +		p++;
> +	}
> +	return p;
> +}
> +
> +static unsigned long get_mount_flags(const char *path)
> +{
> +	FILE *f = fopen("/proc/self/mountinfo", "r");
> +	char *line = NULL;
> +	size_t len = 0;
> +	unsigned long flags = 0;
> +
> +	if (!f) {
> +		WARN("Failed to open /proc/self/mountinfo");
> +		return 0;
> +	}
> +	while (getline(&line, &len, f) != -1) {
> +		char *target, *opts, *p, *saveptr = NULL;
> +		target = get_field(line, 4);
> +		if (!target)
> +			continue;
> +		opts = get_field(target, 2);
> +		if (!opts)
> +			continue;
> +		null_endofword(opts);
> +		for (p = strtok_r(opts, ",", &saveptr); p;
> +			p = strtok_r(NULL, ",", &saveptr)) {
> +			if (strcmp(p, "ro") == 0)
> +				flags |= MS_RDONLY;
> +			else if (strcmp(p, "nodev") == 0)
> +				flags |= MS_NODEV;
> +			else if (strcmp(p, "nosuid") == 0)
> +				flags |= MS_NOSUID;
> +			else if (strcmp(p, "noexec") == 0)
> +				flags |= MS_NOEXEC;
> +			/* XXX todo - we'll have to deal with atime? */
> +		}
> +	}
> +	free(line);
> +	fclose(f);
> +	return flags;
> +}
> +
>  static int mount_entry(const char *fsname, const char *target,
>  		       const char *fstype, unsigned long mountflags,
>  		       const char *data, int optional)
>  {
> +	unsigned long extraflags;
>  	if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
>  		if (optional) {
>  			INFO("failed to mount '%s' on '%s' (optional): %s", fsname,
> @@ -1944,9 +2008,22 @@ static int mount_entry(const char *fsname, const char *target,
>  	}
>  
>  	if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
> +		extraflags = get_mount_flags(target);
> +		DEBUG("flags was %lu, extraflags set to %lu\n", mountflags, extraflags);
> +		if (!(mountflags & MS_REMOUNT) && (mountflags & MS_BIND)) {
> +			if (!(extraflags & ~mountflags))
> +				DEBUG("Skipping remount");
> +				goto skipremount;
> +		}
> +		DEBUG("proceeding with remont");
> +		mountflags |= extraflags;
> +	}
>  
> -		DEBUG("remounting %s on %s to respect bind or remount options",
> -		      fsname, target);
> +
> +	if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
> +		DEBUG("remounting %s on %s to respect bind or remount options %lu (extra %lu)",
> +		      fsname ? fsname : "(none)",
> +		      target ? target : "(none)", mountflags, extraflags);
>  
>  		if (mount(fsname, target, fstype,
>  			  mountflags | MS_REMOUNT, data)) {
> @@ -1963,6 +2040,7 @@ static int mount_entry(const char *fsname, const char *target,
>  		}
>  	}
>  
> +skipremount:
>  	DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
>  
>  	return 0;
> @@ -3888,31 +3966,6 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf)
>  	}
>  }
>  
> -static void null_endofword(char *word)
> -{
> -	while (*word && *word != ' ' && *word != '\t')
> -		word++;
> -	*word = '\0';
> -}
> -
> -/*
> - * skip @nfields spaces in @src
> - */
> -static char *get_field(char *src, int nfields)
> -{
> -	char *p = src;
> -	int i;
> -
> -	for (i = 0; i < nfields; i++) {
> -		while (*p && *p != ' ' && *p != '\t')
> -			p++;
> -		if (!*p)
> -			break;
> -		p++;
> -	}
> -	return p;
> -}
> -
>  static void remount_all_slave(void)
>  {
>  	/* walk /proc/mounts and change any shared entries to slave */
> -- 
> 2.1.0.rc1
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140817/95338d4c/attachment.sig>


More information about the lxc-devel mailing list