[lxc-devel] [PATCH] bdev: allow unprivileged overlayfs snapshots

Stéphane Graber stgraber at ubuntu.com
Tue Feb 11 22:26:38 UTC 2014


On Tue, Feb 11, 2014 at 01:43:19PM -0600, Serge Hallyn wrote:
> Also make sure to chown the new rootfs path to the container owner.
> This is how we make sure that the container root is allowed to write
> under delta0.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

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

Some more kernel work remains to be done (as we discussed) but the LXC
side is sane and with those remaining changes done, file removal should
work too :)

> ---
>  src/lxc/bdev.c | 55 +++++++++++++++++++++++++++++++++++--------------------
>  src/lxc/conf.c | 19 +++++++++++++++++++
>  2 files changed, 54 insertions(+), 20 deletions(-)
> 
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 01c06e1..7f8ab9c 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -2130,6 +2130,31 @@ bool bdev_is_dir(const char *path)
>  }
>  
>  /*
> + * is an unprivileged user allowed to make this kind of snapshot
> + */
> +static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
> +		bool maybesnap)
> +{
> +	if (!t) {
> +		// new type will be same as original
> +		// (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, "overlayfs") == 0 ||
> +				strcmp(b->type, "loop") == 0)
> +			return true;
> +		return false;
> +	}
> +
> +	// 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, "loop") == 0)
> +		return true;
> +	return false;
> +}
> +
> +/*
>   * If we're not snaphotting, then bdev_copy becomes a simple case of mount
>   * the original, mount the new, and rsync the contents.
>   */
> @@ -2180,26 +2205,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
>  		}
>  	}
>  
> -	/* check for privilege */
> -	if (am_unpriv()) {
> -		if (snap && !maybe_snap) {
> -			ERROR("Unprivileged users cannot snapshot");
> -			bdev_put(orig);
> -			return NULL;
> -		}
> -		if (bdevtype && strcmp(bdevtype, "dir") != 0) {
> -			ERROR("Unprivileged users can only make dir copy-clones");
> -			bdev_put(orig);
> -			return NULL;
> -		}
> -		if (strcmp(orig->type, "dir") != 0) {
> -			ERROR("Unprivileged users can only make dir copy-clones");
> -			bdev_put(orig);
> -			return NULL;
> -		}
> -	}
> -
> -
>  	/*
>  	 * special case for snapshot - if caller requested maybe_snapshot and
>  	 * keepbdevtype and backing store is directory, then proceed with a copy
> @@ -2214,6 +2219,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
>  	if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type , "dir") == 0)
>  		bdevtype = "overlayfs";
>  
> +	if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
> +		ERROR("Unsupported snapshot type for unprivileged users");
> +		bdev_put(orig);
> +		return NULL;
> +	}
> +
>  	*needs_rdep = 0;
>  	if (bdevtype && strcmp(orig->type, "dir") == 0 &&
>  			strcmp(bdevtype, "overlayfs") == 0)
> @@ -2232,6 +2243,10 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
>  		bdev_put(new);
>  		return NULL;
>  	}
> +
> +	if (am_unpriv() && chown_mapped_root(new->src, c0->lxc_conf) < 0)
> +		WARN("Failed to update ownership of %s", new->dest);
> +
>  	if (snap)
>  		return new;
>  
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 4e25432..522c590 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -3364,6 +3364,7 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
>  	uid_t rootid;
>  	pid_t pid;
>  	unsigned long val;
> +	char *chownpath = path;
>  
>  	if (!get_mapped_rootid(conf, ID_TYPE_UID, &val)) {
>  		ERROR("No mapping for container root");
> @@ -3371,6 +3372,24 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
>  	}
>  	rootid = (uid_t) val;
>  
> +	/*
> +	 * In case of overlay, we want only the writeable layer
> +	 * to be chowned
> +	 */
> +	if (strncmp(path, "overlayfs:", 10) == 0) {
> +		chownpath = strchr(path, ':');
> +		if (!chownpath) {
> +			ERROR("Bad overlay path: %s", path);
> +			return -1;
> +		}
> +		chownpath = strchr(chownpath+1, ':');
> +		if (!chownpath) {
> +			ERROR("Bad overlay path: %s", path);
> +			return -1;
> +		}
> +		chownpath++;
> +	}
> +	path = chownpath;
>  	if (geteuid() == 0) {
>  		if (chown(path, rootid, -1) < 0) {
>  			ERROR("Error chowning %s", path);
> -- 
> 1.9.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/20140211/e30e1037/attachment.pgp>


More information about the lxc-devel mailing list