[lxc-devel] Unprivilege containers do not work on kernel 3.14.8, 3.15.1

KATOH Yasufumi karma at jazz.email.ne.jp
Tue Jun 24 11:25:12 UTC 2014


>>> On Mon, 23 Jun 2014 20:48:26 +0000
    in message   "Re: [lxc-devel] Unprivilege containers do not work on kernel 3.14.8, 3.15.1"
                  Serge Hallyn-san wrote:

> Good point.  So we'll have to cgroup the pty to our own gid before
> we can do the userns chown.  So

> 	cgroup $(id -g) /dev/pts/3
> 	lxc-usernsexec -m u:0:100000:1 -m u:$(id -u):1000:1 -m g:0:100000:1 -m g:$(id -g):1000:1 -- chown 0 /dev/pts/3

> should do the trick.  Until you hit the next roadblock :)

TAMUKI-san(who maintained lxc-plamo) and I tried to make the patch
:-), then unpriv container now work on my host. Please review it!

But after container start, the console can't use. Is that reason that
the group of tty (on container) or pty (on host) is not tty group? Do
you have any idea?

--------

From 4aed8dd6be5607aa5a66c38b839ad5988ec8ee09 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Tue, 24 Jun 2014 20:12:10 +0900
Subject: [PATCH] Fix to work with unprivileged containers on recent kernel

Change chown_mapped_root() to map in both the root uid and gid, not
just the uid, so as to work with unprivileged containers on recent
kernel.

Signed-off-by: TAMUKI Shoichi <tamuki at linet.gr.jp>
Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 src/lxc/conf.c | 48 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index c8b573a..b2bb899 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3338,7 +3338,7 @@ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype,
 
 	lxc_list_for_each(it, &conf->id_map) {
 		map = it->elem;
-		if (map->idtype != ID_TYPE_UID)
+		if (map->idtype != idtype)
 			continue;
 		if (map->nsid != 0)
 			continue;
@@ -3500,7 +3500,8 @@ void lxc_delete_tty(struct lxc_tty_info *tty_info)
  */
 int chown_mapped_root(char *path, struct lxc_conf *conf)
 {
-	uid_t rootid;
+	uid_t rootuid;
+	gid_t rootgid;
 	pid_t pid;
 	unsigned long val;
 	char *chownpath = path;
@@ -3509,7 +3510,12 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
 		ERROR("No mapping for container root");
 		return -1;
 	}
-	rootid = (uid_t) val;
+	rootuid = (uid_t) val;
+	if (!get_mapped_rootid(conf, ID_TYPE_GID, &val)) {
+		ERROR("No mapping for container root");
+		return -1;
+	}
+	rootgid = (gid_t) val;
 
 	/*
 	 * In case of overlay, we want only the writeable layer
@@ -3530,14 +3536,14 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
 	}
 	path = chownpath;
 	if (geteuid() == 0) {
-		if (chown(path, rootid, -1) < 0) {
+		if (chown(path, rootuid, rootgid) < 0) {
 			ERROR("Error chowning %s", path);
 			return -1;
 		}
 		return 0;
 	}
 
-	if (rootid == geteuid()) {
+	if (rootuid == geteuid()) {
 		// nothing to do
 		INFO("%s: container root is our uid;  no need to chown" ,__func__);
 		return 0;
@@ -3549,13 +3555,20 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
 		return -1;
 	}
 	if (!pid) {
-		int hostuid = geteuid(), ret;
-		char map1[100], map2[100], map3[100];
-		char *args[] = {"lxc-usernsexec", "-m", map1, "-m", map2, "-m",
-				 map3, "--", "chown", "0", path, NULL};
+		int hostuid = geteuid(), hostgid = getegid(), ret;
+		char map1[100], map2[100], map3[100], map4[100];
+		char *args[] = { "lxc-usernsexec", "-m", map1, "-m", map2,
+				"-m", map3, "-m", map4, "--", "chown", "0",
+				path, NULL };
+
+		// This is a trick for chgrp the file that is not owned by myself.
+		if (chown(path, -1, hostgid) < 0) {
+			ERROR("%s: failed to chgrp", path);
+			return -1;
+		}
 
-		// "u:0:rootid:1"
-		ret = snprintf(map1, 100, "u:0:%d:1", rootid);
+		// "u:0:rootuid:1"
+		ret = snprintf(map1, 100, "u:0:%d:1", rootuid);
 		if (ret < 0 || ret >= 100) {
 			ERROR("Error uid printing map string");
 			return -1;
@@ -3568,10 +3581,17 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
 			return -1;
 		}
 
-		// "g:0:hostgid:1"
-		ret = snprintf(map3, 100, "g:0:%d:1", getgid());
+		// "g:0:rootgid:1"
+		ret = snprintf(map3, 100, "g:0:%d:1", rootgid);
 		if (ret < 0 || ret >= 100) {
-			ERROR("Error uid printing map string");
+			ERROR("Error gid printing map string");
+			return -1;
+		}
+
+		// "g:hostgid:hostgid:1"
+		ret = snprintf(map4, 100, "g:%d:%d:1", hostgid, hostgid);
+		if (ret < 0 || ret >= 100) {
+			ERROR("Error gid printing map string");
 			return -1;
 		}
 
-- 
1.9.0



More information about the lxc-devel mailing list