[lxc-devel] [PATCH 1/1] overlayfs_clonepaths: if unpriv then rsync in a userns

Stéphane Graber stgraber at ubuntu.com
Thu Feb 13 15:10:08 UTC 2014


On Thu, Feb 13, 2014 at 12:52:52AM -0600, Serge Hallyn wrote:
> This allows lxc-snapshot and lxc-clone -s from an overlayfs container
> to work unprivileged.  (lxc-clone -s from a directory backed container
> already did work)
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

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

> ---
>  src/lxc/bdev.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
>  src/lxc/bdev.h |  2 +-
>  2 files changed, 62 insertions(+), 10 deletions(-)
> 
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 1df602c..67fe72b 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -442,7 +442,7 @@ static char *dir_new_path(char *src, const char *oldname, const char *name,
>   */
>  static int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	int len, ret;
>  
> @@ -667,7 +667,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
>  
>  static int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	int len, ret;
>  
> @@ -1001,7 +1001,7 @@ static int is_blktype(struct bdev *b)
>  
>  static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	char fstype[100];
>  	uint64_t size = newsize;
> @@ -1374,7 +1374,7 @@ out:
>  
>  static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	if (!orig->dest || !orig->src)
>  		return -1;
> @@ -1626,7 +1626,7 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype)
>   */
>  static int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	char fstype[100];
>  	uint64_t size = newsize;
> @@ -1826,9 +1826,40 @@ static int overlayfs_umount(struct bdev *bdev)
>  	return umount(bdev->dest);
>  }
>  
> +struct rsync_data_char {
> +	char *src;
> +	char *dest;
> +};
> +
> +static int rsync_delta(struct rsync_data_char *data)
> +{
> +	if (setgid(0) < 0) {
> +		ERROR("Failed to setgid to 0");
> +		return -1;
> +	}
> +	if (setgroups(0, NULL) < 0)
> +		WARN("Failed to clear groups");
> +	if (setuid(0) < 0) {
> +		ERROR("Failed to setuid to 0");
> +		return -1;
> +	}
> +	if (do_rsync(data->src, data->dest) < 0) {
> +		ERROR("rsyncing %s to %s", data->src, data->dest);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rsync_delta_wrapper(void *data)
> +{
> +	struct rsync_data_char *arg = data;
> +	return rsync_delta(arg);
> +}
> +
>  static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	if (!snap) {
>  		ERROR("overlayfs is only for snapshot clones");
> @@ -1844,6 +1875,9 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
>  	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;
>  		int ret, len;
> @@ -1864,6 +1898,8 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
>  			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 'overlayfs:lowerdir:upperdir'
>  		len = strlen(delta) + strlen(orig->src) + 12;
> @@ -1897,7 +1933,22 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
>  			free(osrc);
>  			return -ENOMEM;
>  		}
> -		if (do_rsync(odelta, ndelta) < 0) {
> +		if ((ret = mkdir(ndelta, 0755)) < 0) {
> +			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 overlayfs delta");
> @@ -2079,7 +2130,7 @@ static int aufs_umount(struct bdev *bdev)
>  
>  static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
>  		const char *cname, const char *oldpath, const char *lxcpath, int snap,
> -		uint64_t newsize)
> +		uint64_t newsize, struct lxc_conf *conf)
>  {
>  	if (!snap) {
>  		ERROR("aufs is only for snapshot clones");
> @@ -2491,7 +2542,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
>  		return NULL;
>  	}
>  
> -	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath, snap, newsize) < 0) {
> +	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
> +				snap, newsize, c0->lxc_conf) < 0) {
>  		ERROR("failed getting pathnames for cloned storage: %s", src);
>  		bdev_put(orig);
>  		bdev_put(new);
> diff --git a/src/lxc/bdev.h b/src/lxc/bdev.h
> index 250e320..7efc164 100644
> --- a/src/lxc/bdev.h
> +++ b/src/lxc/bdev.h
> @@ -62,7 +62,7 @@ struct bdev_ops {
>  	/* given original mount, rename the paths for cloned container */
>  	int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname,
>  			const char *cname, const char *oldpath, const char *lxcpath,
> -			int snap, uint64_t newsize);
> +			int snap, uint64_t newsize, struct lxc_conf *conf);
>  	bool can_snapshot;
>  };
>  
> -- 
> 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/20140213/4e76d3c2/attachment.pgp>


More information about the lxc-devel mailing list