[lxc-devel] [lxc/master] Support configurations without root mapping

brauner on Github lxc-bot at linuxcontainers.org
Tue Jan 2 23:13:47 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 381 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180102/c0633d43/attachment.bin>
-------------- next part --------------
From c433319551329ff709173bb08541d0fe015d7265 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 2 Jan 2018 22:15:17 +0100
Subject: [PATCH 1/5] conf: adapt idmap helpers

- mapped_hostid_entry()
- idmap_add()

Closes #2033.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 41 +++++++++++++++++------------------------
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 38f868afb..5617ff35f 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3722,8 +3722,8 @@ static int run_userns_fn(void *data)
 	return d->fn(d->arg);
 }
 
-static struct id_map *mapped_hostid_entry(struct lxc_conf *conf, unsigned id,
-					  enum idtype idtype)
+static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf,
+					       unsigned id, enum idtype idtype)
 {
 	struct lxc_list *it;
 	struct id_map *map;
@@ -3740,14 +3740,6 @@ static struct id_map *mapped_hostid_entry(struct lxc_conf *conf, unsigned id,
 		}
 	}
 
-	if (!retmap)
-		return NULL;
-
-	retmap = malloc(sizeof(*retmap));
-	if (!retmap)
-		return NULL;
-
-	memcpy(retmap, map, sizeof(*retmap));
 	return retmap;
 }
 
@@ -3755,27 +3747,28 @@ static struct id_map *mapped_hostid_entry(struct lxc_conf *conf, unsigned id,
  * Allocate a new {g,u}id mapping for the given {g,u}id. Re-use an already
  * existing one or establish a new one.
  */
-static struct id_map *idmap_add(struct lxc_conf *conf, uid_t id, enum idtype type)
+static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, enum idtype type)
 {
 	int hostid_mapped;
-	struct id_map *entry = NULL;
+	struct id_map *entry = NULL, *tmp = NULL;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		return NULL;
 
 	/* Reuse existing mapping. */
-	entry = mapped_hostid_entry(conf, id, type);
-	if (entry)
-		return entry;
+	tmp = find_mapped_hostid_entry(conf, id, type);
+	if (tmp)
+		return memcpy(entry, tmp, sizeof(*entry));
 
 	/* Find new mapping. */
 	hostid_mapped = find_unmapped_nsid(conf, type);
 	if (hostid_mapped < 0) {
-		DEBUG("failed to find free mapping for id %d", id);
+		DEBUG("Failed to find free mapping for id %d", id);
+		free(entry);
 		return NULL;
 	}
 
-	entry = malloc(sizeof(*entry));
-	if (!entry)
-		return NULL;
-
 	entry->idtype = type;
 	entry->nsid = hostid_mapped;
 	entry->hostid = (unsigned long)id;
@@ -3884,10 +3877,10 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 
 	/* Check whether the {g,u}id of the user has a mapping. */
 	if (!host_uid_map)
-		host_uid_map = idmap_add(conf, euid, ID_TYPE_UID);
+		host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID);
 
 	if (!host_gid_map)
-		host_gid_map = idmap_add(conf, egid, ID_TYPE_GID);
+		host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
 
 	if (!host_uid_map) {
 		DEBUG("failed to find mapping for uid %d", euid);
@@ -4095,12 +4088,12 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
 
 	/* Check whether the {g,u}id of the user has a mapping. */
 	if (!host_uid_map)
-		host_uid_map = idmap_add(conf, euid, ID_TYPE_UID);
+		host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID);
 	else
 		host_uid_map = container_root_uid;
 
 	if (!host_gid_map)
-		host_gid_map = idmap_add(conf, egid, ID_TYPE_GID);
+		host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
 	else
 		host_gid_map = container_root_gid;
 

From db7cfe23abe4312af4b133cdac868ce696d822d3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 2 Jan 2018 22:31:16 +0100
Subject: [PATCH 2/5] conf: adapt userns_exec_1()

Closes #2033.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 100 ++++++++++++++++++++++++++++++---------------------------
 1 file changed, 53 insertions(+), 47 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 5617ff35f..de661c004 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3722,6 +3722,44 @@ static int run_userns_fn(void *data)
 	return d->fn(d->arg);
 }
 
+static struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
+					     enum idtype idtype)
+{
+	struct lxc_list *it;
+	struct id_map *map;
+	struct id_map *retmap = NULL;
+
+	lxc_list_for_each(it, &conf->id_map) {
+		map = it->elem;
+		if (map->idtype != idtype)
+			continue;
+
+		if (id >= map->nsid && id < map->nsid + map->range) {
+			retmap = map;
+			break;
+		}
+	}
+
+	return retmap;
+}
+
+static struct id_map *mapped_nsid_add(struct lxc_conf *conf, unsigned id,
+				      enum idtype idtype)
+{
+	struct id_map *map, *retmap;
+
+	map = find_mapped_nsid_entry(conf, id, idtype);
+	if (!map)
+		return NULL;
+
+	retmap = malloc(sizeof(*retmap));
+	if (!retmap)
+		return NULL;
+
+	memcpy(retmap, map, sizeof(*retmap));
+	return retmap;
+}
+
 static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf,
 					       unsigned id, enum idtype idtype)
 {
@@ -3824,56 +3862,24 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 	close(p[0]);
 	p[0] = -1;
 
+	/* Find container root mappings. */
 	euid = geteuid();
-	egid = getegid();
-
-	/* Find container root. */
-	lxc_list_for_each(it, &conf->id_map) {
-		map = it->elem;
-
-		if (map->nsid != 0)
-			continue;
-
-		if (map->idtype == ID_TYPE_UID && container_root_uid == NULL) {
-			container_root_uid = malloc(sizeof(*container_root_uid));
-			if (!container_root_uid)
-				goto on_error;
-			container_root_uid->idtype = map->idtype;
-			container_root_uid->hostid = map->hostid;
-			container_root_uid->nsid = 0;
-			container_root_uid->range = map->range;
-
-			/* Check if container root mapping contains a mapping
-			 * for user's uid.
-			 */
-			if (euid >= map->hostid && euid < map->hostid + map->range)
-				host_uid_map = container_root_uid;
-		} else if (map->idtype == ID_TYPE_GID && container_root_gid == NULL) {
-			container_root_gid = malloc(sizeof(*container_root_gid));
-			if (!container_root_gid)
-				goto on_error;
-			container_root_gid->idtype = map->idtype;
-			container_root_gid->hostid = map->hostid;
-			container_root_gid->nsid = 0;
-			container_root_gid->range = map->range;
-
-			/* Check if container root mapping contains a mapping
-			 * for user's gid.
-			 */
-			if (egid >= map->hostid && egid < map->hostid + map->range)
-				host_gid_map = container_root_gid;
-		}
-
-		/* Found container root. */
-		if (container_root_uid && container_root_gid)
-			break;
+	container_root_uid = mapped_nsid_add(conf, 0, ID_TYPE_UID);
+	if (!container_root_uid) {
+		DEBUG("Failed to find mapping for container root uid %d", 0);
+		goto on_error;
 	}
+	if (euid >= container_root_uid->hostid && euid < container_root_uid->hostid + container_root_uid->range)
+		host_uid_map = container_root_uid;
 
-	/* This is actually checked earlier but it can't hurt. */
-	if (!container_root_uid || !container_root_gid) {
-		ERROR("no mapping for container root found");
+	egid = getegid();
+	container_root_gid = mapped_nsid_add(conf, 0, ID_TYPE_GID);
+	if (!container_root_gid) {
+		DEBUG("Failed to find mapping for container root gid %d", 0);
 		goto on_error;
 	}
+	if (egid >= container_root_gid->hostid && egid < container_root_gid->hostid + container_root_gid->range)
+		host_gid_map = container_root_gid;
 
 	/* Check whether the {g,u}id of the user has a mapping. */
 	if (!host_uid_map)
@@ -3883,12 +3889,12 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 		host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
 
 	if (!host_uid_map) {
-		DEBUG("failed to find mapping for uid %d", euid);
+		DEBUG("Failed to find mapping for uid %d", euid);
 		goto on_error;
 	}
 
 	if (!host_gid_map) {
-		DEBUG("failed to find mapping for gid %d", egid);
+		DEBUG("Failed to find mapping for gid %d", egid);
 		goto on_error;
 	}
 

From 46ad64ab261e01780b9058e26824b91d7fd5ceb6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 2 Jan 2018 23:27:55 +0100
Subject: [PATCH 3/5] conf{ile}: detect ns{g,u}id mapping for root

Closes #2033.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c    |  2 ++
 src/lxc/conf.h    | 10 +++++++++-
 src/lxc/confile.c | 10 ++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index de661c004..9f7f8d8fa 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2573,6 +2573,8 @@ struct lxc_conf *lxc_conf_init(void)
 	lxc_list_init(&new->caps);
 	lxc_list_init(&new->keepcaps);
 	lxc_list_init(&new->id_map);
+	new->root_nsuid_map = NULL;
+	new->root_nsgid_map = NULL;
 	lxc_list_init(&new->includes);
 	lxc_list_init(&new->aliens);
 	lxc_list_init(&new->environment);
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index b7ddf1d3f..371238220 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -282,7 +282,15 @@ struct lxc_conf {
 	signed long personality;
 	struct utsname *utsname;
 	struct lxc_list cgroup;
-	struct lxc_list id_map;
+	struct {
+		struct lxc_list id_map;
+		/* Pointer to the idmap entry for the container's root uid in
+		 * the id_map list. Do not free! */
+		struct id_map *root_nsuid_map;
+		/* Pointer to the idmap entry for the container's root gid in
+		 * the id_map list. Do not free! */
+		struct id_map *root_nsgid_map;
+	};
 	struct lxc_list network;
 	int auto_mounts;
 	struct lxc_list mount_list;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index cde4f3e86..0033d5597 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1681,6 +1681,16 @@ static int set_config_idmaps(const char *key, const char *value,
 	idmap->range = range;
 	idmaplist->elem = idmap;
 	lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
+
+	if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_UID)
+		if (idmap->nsid == 0)
+			lxc_conf->root_nsuid_map = idmap;
+
+
+	if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_GID)
+		if (idmap->nsid == 0)
+			lxc_conf->root_nsgid_map = idmap;
+
 	idmap = NULL;
 
 	return 0;

From 4160c3a08836bce8707e7cf89e84200c79f1402c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 2 Jan 2018 23:41:10 +0100
Subject: [PATCH 4/5] cgfsng: use init {g,u}id

If no id mapping for the container's root id is defined try to us the id
mappings specified via lxc.init.{g,u}id.

Closes #2033.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 55 ++++++++++++++++++++++++++++++------------------
 src/lxc/conf.c           | 17 +++++++++++----
 src/lxc/confile.c        |  2 +-
 src/lxc/start.c          |  9 +++++++-
 4 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index e13d5cadf..28ddc827d 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1267,25 +1267,41 @@ static int cgroup_rmdir(char *dirname)
 	return r;
 }
 
+struct generic_userns_exec_data {
+	struct cgfsng_handler_data *d;
+	struct lxc_conf *conf;
+	uid_t origuid; /* target uid in parent namespace */
+	char *path;
+};
+
 static int rmdir_wrapper(void *data)
 {
-	char *path = data;
+	struct generic_userns_exec_data *arg = data;
+	uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid;
+	gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid;
 
-	if (setresgid(0,0,0) < 0)
+	if (setresgid(nsgid, nsgid, nsgid) < 0)
 		SYSERROR("Failed to setgid to 0");
-	if (setresuid(0,0,0) < 0)
+	if (setresuid(nsuid, nsuid, nsuid) < 0)
 		SYSERROR("Failed to setuid to 0");
 	if (setgroups(0, NULL) < 0)
 		SYSERROR("Failed to clear groups");
 
-	return cgroup_rmdir(path);
+	return cgroup_rmdir(arg->path);
 }
 
 void recursive_destroy(char *path, struct lxc_conf *conf)
 {
 	int r;
+	struct generic_userns_exec_data wrap;
+
+	wrap.origuid = 0;
+	wrap.d = NULL;
+	wrap.path = path;
+	wrap.conf = conf;
+
 	if (conf && !lxc_list_empty(&conf->id_map))
-		r = userns_exec_1(conf, rmdir_wrapper, path, "rmdir_wrapper");
+		r = userns_exec_1(conf, rmdir_wrapper, &wrap, "rmdir_wrapper");
 	else
 		r = cgroup_rmdir(path);
 
@@ -1445,11 +1461,6 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
 	return true;
 }
 
-struct chown_data {
-	struct cgfsng_handler_data *d;
-	uid_t origuid; /* target uid in parent namespace */
-};
-
 /*
  * chgrp the container cgroups to container group.  We leave
  * the container owner as cgroup owner.  So we must make the
@@ -1460,13 +1471,15 @@ struct chown_data {
  */
 static int chown_cgroup_wrapper(void *data)
 {
-	struct chown_data *arg = data;
-	uid_t destuid;
 	int i;
+	uid_t destuid;
+	struct generic_userns_exec_data *arg = data;
+	uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid;
+	gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid;
 
-	if (setresgid(0,0,0) < 0)
+	if (setresgid(nsgid, nsgid, nsgid) < 0)
 		SYSERROR("Failed to setgid to 0");
-	if (setresuid(0,0,0) < 0)
+	if (setresuid(nsuid, nsuid, nsuid) < 0)
 		SYSERROR("Failed to setuid to 0");
 	if (setgroups(0, NULL) < 0)
 		SYSERROR("Failed to clear groups");
@@ -1476,7 +1489,7 @@ static int chown_cgroup_wrapper(void *data)
 	for (i = 0; hierarchies[i]; i++) {
 		char *fullpath, *path = hierarchies[i]->fullcgpath;
 
-		if (chown(path, destuid, 0) < 0) {
+		if (chown(path, destuid, nsgid) < 0) {
 			SYSERROR("Error chowning %s to %d", path, (int) destuid);
 			return -1;
 		}
@@ -1494,7 +1507,7 @@ static int chown_cgroup_wrapper(void *data)
 		 * insists on doing)
 		 */
 		fullpath = must_make_path(path, "tasks", NULL);
-		if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT)
+		if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT)
 			WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
 			     strerror(errno));
 		if (chmod(fullpath, 0664) < 0)
@@ -1513,7 +1526,7 @@ static int chown_cgroup_wrapper(void *data)
 			continue;
 
 		fullpath = must_make_path(path, "cgroup.subtree_control", NULL);
-		if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT)
+		if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT)
 			WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
 			     strerror(errno));
 		if (chmod(fullpath, 0664) < 0)
@@ -1521,7 +1534,7 @@ static int chown_cgroup_wrapper(void *data)
 		free(fullpath);
 
 		fullpath = must_make_path(path, "cgroup.threads", NULL);
-		if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT)
+		if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT)
 			WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
 			     strerror(errno));
 		if (chmod(fullpath, 0664) < 0)
@@ -1535,7 +1548,7 @@ static int chown_cgroup_wrapper(void *data)
 static bool cgfsng_chown(void *hdata, struct lxc_conf *conf)
 {
 	struct cgfsng_handler_data *d = hdata;
-	struct chown_data wrap;
+	struct generic_userns_exec_data wrap;
 
 	if (!d)
 		return false;
@@ -1543,8 +1556,10 @@ static bool cgfsng_chown(void *hdata, struct lxc_conf *conf)
 	if (lxc_list_empty(&conf->id_map))
 		return true;
 
-	wrap.d = d;
 	wrap.origuid = geteuid();
+	wrap.path = NULL;
+	wrap.d = d;
+	wrap.conf = conf;
 
 	if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
 			  "chown_cgroup_wrapper") < 0) {
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 9f7f8d8fa..f7500511d 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2828,20 +2828,27 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
  * Return true if id was found, false otherwise.
  */
 bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype,
-			unsigned long *val)
+		       unsigned long *val)
 {
 	struct lxc_list *it;
 	struct id_map *map;
+	unsigned nsid;
+
+	if (idtype == ID_TYPE_UID)
+		nsid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid;
+	else
+		nsid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid;
 
 	lxc_list_for_each(it, &conf->id_map) {
 		map = it->elem;
 		if (map->idtype != idtype)
 			continue;
-		if (map->nsid != 0)
+		if (map->nsid != nsid)
 			continue;
 		*val = map->hostid;
 		return true;
 	}
+
 	return false;
 }
 
@@ -3839,6 +3846,8 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 	struct id_map *map;
 	char c = '1';
 	int ret = -1, status = -1;
+	uid_t nsuid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid;
+	gid_t nsgid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid;
 	struct lxc_list *idmap = NULL, *tmplist = NULL;
 	struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
 		      *host_uid_map = NULL, *host_gid_map = NULL;
@@ -3866,7 +3875,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 
 	/* Find container root mappings. */
 	euid = geteuid();
-	container_root_uid = mapped_nsid_add(conf, 0, ID_TYPE_UID);
+	container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID);
 	if (!container_root_uid) {
 		DEBUG("Failed to find mapping for container root uid %d", 0);
 		goto on_error;
@@ -3875,7 +3884,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
 		host_uid_map = container_root_uid;
 
 	egid = getegid();
-	container_root_gid = mapped_nsid_add(conf, 0, ID_TYPE_GID);
+	container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID);
 	if (!container_root_gid) {
 		DEBUG("Failed to find mapping for container root gid %d", 0);
 		goto on_error;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 0033d5597..65f13ac56 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1687,7 +1687,7 @@ static int set_config_idmaps(const char *key, const char *value,
 			lxc_conf->root_nsuid_map = idmap;
 
 
-	if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_GID)
+	if (!lxc_conf->root_nsgid_map && idmap->idtype == ID_TYPE_GID)
 		if (idmap->nsid == 0)
 			lxc_conf->root_nsgid_map = idmap;
 
diff --git a/src/lxc/start.c b/src/lxc/start.c
index b57661f8c..d5b6f56e7 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -999,7 +999,14 @@ static int do_start(void *data)
 	 * privilege over our namespace.
 	 */
 	if (!lxc_list_empty(&handler->conf->id_map)) {
-		ret = lxc_switch_uid_gid(0, 0);
+		uid_t nsuid = (handler->conf->root_nsuid_map != NULL)
+				  ? 0
+				  : handler->conf->init_uid;
+		gid_t nsgid = (handler->conf->root_nsgid_map != NULL)
+				  ? 0
+				  : handler->conf->init_gid;
+
+		ret = lxc_switch_uid_gid(nsuid, nsgid);
 		if (ret < 0)
 			goto out_warn_father;
 

From f49007111ea2f1cffa6de43259ccf74e93a295c9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 3 Jan 2018 00:11:38 +0100
Subject: [PATCH 5/5] conf: detect if devpts can be mounted with gid=5

Closes #2033.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 59 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index f7500511d..9a0360907 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1416,20 +1416,46 @@ static int setup_pivot_root(const struct lxc_rootfs *rootfs)
 	return 0;
 }
 
-static int lxc_setup_devpts(int num_pts)
+static struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
+					     enum idtype idtype)
+{
+	struct lxc_list *it;
+	struct id_map *map;
+	struct id_map *retmap = NULL;
+
+	lxc_list_for_each(it, &conf->id_map) {
+		map = it->elem;
+		if (map->idtype != idtype)
+			continue;
+
+		if (id >= map->nsid && id < map->nsid + map->range) {
+			retmap = map;
+			break;
+		}
+	}
+
+	return retmap;
+}
+
+static int lxc_setup_devpts(struct lxc_conf *conf)
 {
 	int ret;
-	const char *default_devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
+	const char *default_devpts_mntopts;
 	char devpts_mntopts[256];
 
-	if (!num_pts) {
+	if (conf->pts <= 0) {
 		DEBUG("no new devpts instance will be mounted since no pts "
 		      "devices are requested");
 		return 0;
 	}
 
+	if (!find_mapped_nsid_entry(conf, 5, ID_TYPE_GID))
+		default_devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620";
+	else
+		default_devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
+
 	ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%d",
-		       default_devpts_mntopts, num_pts);
+		       default_devpts_mntopts, conf->pts);
 	if (ret < 0 || (size_t)ret >= sizeof(devpts_mntopts))
 		return -1;
 
@@ -1452,7 +1478,7 @@ static int lxc_setup_devpts(int num_pts)
 	}
 
 	/* Mount new devpts instance. */
-	ret = mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, devpts_mntopts);
+	ret = mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, devpts_mntopts);
 	if (ret < 0) {
 		SYSERROR("failed to mount new devpts instance");
 		return -1;
@@ -3323,7 +3349,7 @@ int lxc_setup(struct lxc_handler *handler)
 		return -1;
 	}
 
-	if (lxc_setup_devpts(lxc_conf->pts)) {
+	if (lxc_setup_devpts(lxc_conf)) {
 		ERROR("failed to setup the new pts instance");
 		return -1;
 	}
@@ -3731,27 +3757,6 @@ static int run_userns_fn(void *data)
 	return d->fn(d->arg);
 }
 
-static struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
-					     enum idtype idtype)
-{
-	struct lxc_list *it;
-	struct id_map *map;
-	struct id_map *retmap = NULL;
-
-	lxc_list_for_each(it, &conf->id_map) {
-		map = it->elem;
-		if (map->idtype != idtype)
-			continue;
-
-		if (id >= map->nsid && id < map->nsid + map->range) {
-			retmap = map;
-			break;
-		}
-	}
-
-	return retmap;
-}
-
 static struct id_map *mapped_nsid_add(struct lxc_conf *conf, unsigned id,
 				      enum idtype idtype)
 {


More information about the lxc-devel mailing list