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

Serge Hallyn serge.hallyn at ubuntu.com
Wed Jun 25 14:58:45 UTC 2014


Quoting KATOH Yasufumi (karma at jazz.email.ne.jp):
> >>> On Tue, 24 Jun 2014 20:25:12 +0900
>     in message   "Re: [lxc-devel] Unprivilege containers do not work on kernel 3.14.8,	3.15.1"
>                   KATOH Yasufumi-san wrote:
> 
> > >>> 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
> 
> s/cgroup/chgrp/ ? (^^;
> 
> > > 	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?
> 
> I tried to resolv this, then
> 
>   chgrp 100 /dev/pts/3
>   lxc-usernsexec -m u:0:100000:1 -m u:1000:1000:1 \
>   > -m g:0:100000:1 -m g:100:100:1 -m g:5:100005:1 \
>   > -- chown 0:5 /dev/pts/3
> 
>  (My uid:gid = 1000:100, gid of tty = 5)
> 
> This works fine :-)

Nice :)

> I updated the patch. After applying, foreground run of lxc-start and
> lxc-console work fine. :-) Please review it:

It looks good to me!

It sounds like you've tested this, but I can't quite tell if you feel it
is ready for inclusion.  If you feel it is, please resend it as just the
patch, I'll look over it again and ack it.

> From e2f2847b00ceea387c865c0104b1c6ed4a6fc7df Mon Sep 17 00:00:00 2001
> From: KATOH Yasufumi <karma at jazz.email.ne.jp>
> Date: Wed, 25 Jun 2014 17:21:10 +0900
> Subject: [PATCH v2] 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 | 69 ++++++++++++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 55 insertions(+), 14 deletions(-)
> 
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index c8b573a..83d7267 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,27 @@ 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], map5[100], chown_arg[100];
> +		char *args[] = { "lxc-usernsexec", "-m", map1, "-m", map2,
> +				"-m", map3, "-m", map4, "-m", map5, 
> +				"--", "chown", chown_arg, path, NULL };
> +		struct stat orig_stat;
> +
> +		// save original gid of "path"
> +		if (stat(path, &orig_stat) < 0) {
> +			ERROR("%s: failed to stat %s", __func__, path);
> +			return -1;
> +		}
>  
> -		// "u:0:rootid:1"
> -		ret = snprintf(map1, 100, "u:0:%d:1", rootid);
> +		// This is a trick for chgrp the file that is not owned by oneself.
> +		if (chown(path, -1, hostgid) < 0) {
> +			ERROR("Error chgrp %s", path);
> +			return -1;
> +		}
> +
> +		// "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 +3588,31 @@ 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;
> +		}
> +
> +		// "g:(orig_stat.st_gid):rootgid+(orig_stat.st_gid):1"
> +		ret = snprintf(map5, 100, "g:%d:%d:1", orig_stat.st_gid, rootgid+orig_stat.st_gid);
> +		if (ret < 0 || ret >= 100) {
> +			ERROR("Error gid printing map string");
> +			return -1;
> +		}
> +
> +		// owner:group arg of chown
> +		ret = snprintf(chown_arg, 100, "0:%d", orig_stat.st_gid);
> +		if (ret < 0 || ret >= 100) {
> +			ERROR("Error chown argument string");
>  			return -1;
>  		}
>  
> -- 
> 1.9.0
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel


More information about the lxc-devel mailing list