[lxc-devel] [PATCH] btrfs: support unprivileged create and clone

Stéphane Graber stgraber at ubuntu.com
Wed May 7 03:29:58 UTC 2014


On Tue, May 06, 2014 at 08:50:45PM +0000, Serge Hallyn wrote:
> btrfs subvolume ioctls are usable by unprivileged users, so allow
> unprivileged containers to reside on btrfs.
> 
> This patch does not yet enable destroy.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

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

> ---
>  src/lxc/bdev.c         |   41 +++++++++++++++++++++++++++++++++--------
>  src/lxc/lxc_create.c   |    5 +++--
>  src/lxc/lxccontainer.c |    4 ++--
>  3 files changed, 38 insertions(+), 12 deletions(-)
> 
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 49ba8ae..20e9fb3 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -66,6 +66,11 @@
>  
>  lxc_log_define(bdev, lxc);
>  
> +struct rsync_data_char {
> +	char *src;
> +	char *dest;
> +};
> +
>  static int do_rsync(const char *src, const char *dest)
>  {
>  	// call out to rsync
> @@ -1433,6 +1438,22 @@ out:
>  	return ret;
>  }
>  
> +static int btrfs_snapshot_wrapper(void *data)
> +{
> +	struct rsync_data_char *arg = 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;
> +	}
> +	return btrfs_snapshot(arg->src, arg->dest);
> +}
> +
>  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, struct lxc_conf *conf)
> @@ -1467,8 +1488,14 @@ static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *old
>  	if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
>  		return -1;
>  
> -	if (snap)
> -		return btrfs_snapshot(orig->dest, new->dest);
> +	if (snap) {
> +		struct rsync_data_char sdata;
> +		if (!am_unpriv())
> +			return btrfs_snapshot(orig->dest, new->dest);
> +		sdata.dest = new->dest;
> +		sdata.src = orig->dest;
> +		return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata);
> +	}
>  
>  	if (rmdir(new->dest) < 0 && errno != -ENOENT) {
>  		SYSERROR("removing %s", new->dest);
> @@ -1510,6 +1537,8 @@ static int btrfs_destroy(struct bdev *orig)
>  	args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
>  	ret = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
>  	INFO("btrfs: snapshot create ioctl returned %d", ret);
> +	if (ret < 0 && errno == EPERM)
> +		INFO("Is the rootfs mounted with -o user_subvol_rm_allowed?");
>  
>  	free(newfull);
>  	close(fd);
> @@ -1887,11 +1916,6 @@ 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) {
> @@ -2538,6 +2562,7 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
>  		// overlayfs -- which is also allowed)
>  		if (strcmp(b->type, "dir") == 0 ||
>  				strcmp(b->type, "overlayfs") == 0 ||
> +				strcmp(b->type, "btrfs") == 0 ||
>  				strcmp(b->type, "loop") == 0)
>  			return true;
>  		return false;
> @@ -2546,7 +2571,7 @@ 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, "loop") == 0)
> +			strcmp(t, "btrfs") == 0 || strcmp(t, "loop") == 0)
>  		return true;
>  	return false;
>  }
> diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
> index caca056..2cc866a 100644
> --- a/src/lxc/lxc_create.c
> +++ b/src/lxc/lxc_create.c
> @@ -229,8 +229,9 @@ int main(int argc, char *argv[])
>  			fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
>  			exit(1);
>  		}
> -		if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset")) {
> -			fprintf(stderr, "Unprivileged users can only create directory backed containers\n");
> +		if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset") &&
> +				strcmp(my_args.bdevtype, "btrfs")) {
> +			fprintf(stderr, "Unprivileged users cannot create %s containers", my_args.bdevtype);
>  			exit(1);
>  		}
>  	}
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 270b8fc..9e23c7b 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -918,9 +918,9 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
>  				}
>  			}
>  		}
> -		if (strcmp(bdev->type, "dir") != 0) {
> +		if (strcmp(bdev->type, "dir") && strcmp(bdev->type, "btrfs")) {
>  			if (geteuid() != 0) {
> -				ERROR("non-root users can only create directory-backed containers");
> +				ERROR("non-root users can only create btrfs and directory-backed containers");
>  				exit(1);
>  			}
>  			if (bdev->ops->mount(bdev) < 0) {
> -- 
> 1.7.9.5
> 
> _______________________________________________
> 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/20140506/7555d026/attachment.sig>


More information about the lxc-devel mailing list