[lxc-devel] [PATCH] aufs: Support unprivileged clone, mount

Serge Hallyn serge.hallyn at ubuntu.com
Tue May 26 19:32:10 UTC 2015


Quoting KATOH Yasufumi (karma at jazz.email.ne.jp):
> Current aufs supports FS_USERNS_MOUNT by using allow_userns module
> parameter. It allows root in userns to mount aufs.
> 
> This patch allows an unprivileged container to use aufs. The value of
> xino option is changed to /dev/shm/aufs.xino that an unpriv user can
> write.
> 
> Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

> ---
>  src/lxc/bdev.c | 68 ++++++++++++++++++++++++++++++++--------------------------
>  1 file changed, 38 insertions(+), 30 deletions(-)
> 
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 61bbe6d..f0a13a9 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -2557,12 +2557,12 @@ static int aufs_detect(const char *path)
>  //
>  static int aufs_mount(struct bdev *bdev)
>  {
> -	char *options, *dup, *lower, *upper, *rundir;
> +	char *options, *dup, *lower, *upper;
>  	int len;
>  	unsigned long mntflags;
>  	char *mntdata;
> -	char *runpath;
>  	int ret;
> +	const char *xinopath = "/dev/shm/aufs.xino";
>  
>  	if (strcmp(bdev->type, "aufs"))
>  		return -22;
> @@ -2588,41 +2588,24 @@ static int aufs_mount(struct bdev *bdev)
>  	// TODO We should check whether bdev->src is a blockdev, and if so
>  	// but for now, only support aufs of a basic directory
>  
> -	rundir = get_rundir();
> -	if (!rundir)
> -		return -1;
> -
> -	len = strlen(rundir) + strlen("/lxc") + 1;
> -	runpath = alloca(len);
> -	ret = snprintf(runpath, len, "%s/lxc", rundir);
> -	if (ret < 0 || ret >= len) {
> -		free(mntdata);
> -		free(rundir);
> -		return -1;
> -	}
> -	if (mkdir_p(runpath, 0755) < 0) {
> -		free(mntdata);
> -		free(rundir);
> -		return -1;
> -	}
> -
>  	// AUFS does not work on top of certain filesystems like (XFS or Btrfs)
> -	// so add xino=RUNDIR/lxc/aufs.xino parameter to mount options
> +	// so add xino=/dev/shm/aufs.xino parameter to mount options.
> +	// The same xino option can be specified to multiple aufs mounts, and
> +	// a xino file is not shared among multiple aufs mounts.
>  	//
>  	// see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.html
> +	//     http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05126.html
>  	if (mntdata) {
> -		len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,,xino=/aufs.xino") + strlen(mntdata) + 1;
> +		len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,,xino=") + strlen(mntdata) + 1;
>  		options = alloca(len);
> -		ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s/aufs.xino", upper, lower, mntdata, runpath);
> +		ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s", upper, lower, mntdata, xinopath);
>  	}
>  	else {
> -		len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,xino=/aufs.xino") + 1;
> +		len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,xino=") + 1;
>  		options = alloca(len);
> -		ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s/aufs.xino", upper, lower, runpath);
> +		ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s", upper, lower, xinopath);
>  	}
>  
> -	free(rundir);
> -
>  	if (ret < 0 || ret >= len) {
>  		free(mntdata);
>  		return -1;
> @@ -2665,6 +2648,9 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
>  	if (mkdir_p(new->dest, 0755) < 0)
>  		return -1;
>  
> +	if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0)
> +		WARN("Failed to update ownership of %s", new->dest);
> +
>  	if (strcmp(orig->type, "dir") == 0) {
>  		char *delta, *lastslash;
>  		int ret, len, lastslashidx;
> @@ -2689,6 +2675,8 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
>  			free(delta);
>  			return -1;
>  		}
> +		if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
> +			WARN("Failed to update ownership of %s", delta);
>  
>  		// the src will be 'aufs:lowerdir:upperdir'
>  		len = strlen(delta) + strlen(orig->src) + 12;
> @@ -2722,7 +2710,23 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
>  			free(osrc);
>  			return -ENOMEM;
>  		}
> -		if (do_rsync(odelta, ndelta) < 0) {
> +		if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
> +			SYSERROR("error: mkdir %s", ndelta);
> +			free(osrc);
> +			free(ndelta);
> +			return -1;
> +		}
> +		if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
> +			WARN("Failed to update ownership of %s", ndelta);
> +
> +		struct rsync_data_char rdata;
> +		rdata.src = odelta;
> +		rdata.dest = ndelta;
> +		if (am_unpriv())
> +			ret = userns_exec_1(conf, rsync_delta_wrapper, &rdata);
> +		else
> +			ret = rsync_delta(&rdata);
> +		if (ret) {
>  			free(osrc);
>  			free(ndelta);
>  			ERROR("copying aufs delta");
> @@ -3311,6 +3315,7 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
>  		// (unless snap && b->type == dir, in which case it will be
>  		// overlayfs -- which is also allowed)
>  		if (strcmp(b->type, "dir") == 0 ||
> +				strcmp(b->type, "aufs") == 0 ||
>  				strcmp(b->type, "overlayfs") == 0 ||
>  				strcmp(b->type, "btrfs") == 0 ||
>  				strcmp(b->type, "loop") == 0)
> @@ -3320,8 +3325,11 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
>  
>  	// unprivileged users can copy and snapshot dir, overlayfs,
>  	// and loop.  In particular, not zfs, btrfs, or lvm.
> -	if (strcmp(t, "dir") == 0 || strcmp(t, "overlayfs") == 0 ||
> -			strcmp(t, "btrfs") == 0 || strcmp(t, "loop") == 0)
> +	if (strcmp(t, "dir") == 0 ||
> +		strcmp(t, "aufs") == 0 ||
> +		strcmp(t, "overlayfs") == 0 ||
> +		strcmp(t, "btrfs") == 0 ||
> +		strcmp(t, "loop") == 0)
>  		return true;
>  	return false;
>  }
> -- 
> 2.2.1
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel


More information about the lxc-devel mailing list