[lxc-devel] [RFC] Unprivileged aufs container

KATOH Yasufumi karma at jazz.email.ne.jp
Tue Apr 21 11:30:51 UTC 2015


Hi,

Current aufs supports FS_USERNS_MOUNT by using module parameter
'allow_userns'. So we can start an unprivileged container using
aufs. (But ubuntu kernel do not support it?)
  https://github.com/sfjro/aufs3-linux/commit/548fa48dbf52ad80e55deb8ca945c4f7814dbf94

How about support unprivileged aufs container?

I tried creating the patch. (but I have not done enough test.)

This moves the place of xino file to /dev/shm, because get_rundir
always return '/run' when mount aufs, so unpriv container can't
write. This idea is from
docker(https://github.com/docker/docker/pull/826).


From 2c489a3887d904f2a4fe771d250fda55947f27d3 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Tue, 21 Apr 2015 19:29:19 +0900
Subject: [PATCH] aufs: Support unprivileged clone, mount

Current aufs supports FS_USERNS_MOUNT by using allow_userns module parameter.

Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 src/lxc/bdev.c | 62 ++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 26 deletions(-)

diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
index cf7c043..051c34d 100644
--- a/src/lxc/bdev.c
+++ b/src/lxc/bdev.c
@@ -2552,12 +2552,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/lxc";
 
 	if (strcmp(bdev->type, "aufs"))
 		return -22;
@@ -2583,41 +2583,26 @@ 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) {
+	if (mkdir_p(xinopath, 0755) < 0) {
 		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/lxc/aufs.xino parameter to mount options
 	//
 	// see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.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=/aufs.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/aufs.xino", 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=/aufs.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/aufs.xino", upper, lower, xinopath);
 	}
 
-	free(rundir);
-
 	if (ret < 0 || ret >= len) {
 		free(mntdata);
 		return -1;
@@ -2660,6 +2645,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;
@@ -2684,6 +2672,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;
@@ -2717,7 +2707,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");
@@ -3306,6 +3312,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)
@@ -3315,8 +3322,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



More information about the lxc-devel mailing list