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

Serge Hallyn serge.hallyn at ubuntu.com
Tue May 6 20:50:45 UTC 2014


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>
---
 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



More information about the lxc-devel mailing list