From 989351a22878f280fdd26324e6488ed21f57fbae Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 5 Sep 2017 17:43:31 +0200 Subject: [PATCH] conf: fix userns_exec_1() A bit of context: userns_exec_1() is only used to operate based on privileges for the user's own {g,u}id on the host and for the container root's unmapped {g,u}id. This means we require only to establish a mapping from: - the container root {g,u}id as seen from the host -> user's host {g,u}id - the container root -> some sub{g,u}id This function however was buggy. It relied on some pointer pointing to the same memory, namely specific idmap entries in the idmap list in the container's in-memory configuration. However, due to a stupid mistake of mine, the pointers to be compared pointed to freshly allocated memory. They were never pointing to the intended memory locations. To reproduce what I'm talking about prior to this commit simply place: chb:999:1000000000 chb:999:1 chb:1000:1 in /etc/sub{g,u}id then create a container which requests the following idmappings: lxc.idmap = u 0 999 999 lxc.idmap = g 0 999 1000000000 and start the container. What we *would expect* is for liblxc to establish the following mapping: newuidmap 0 999 999 newgidmap 0 999 1000000000 since all required mappings are present. Due to the buggy pointer comparisons what happened was: newuidmap 0 999 999 0 999 999 newgidmap 0 999 1000000000 0 999 1000000000 Let's fix this. Signed-off-by: Christian Brauner --- src/lxc/conf.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 476073e96..fd74a66b3 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3663,6 +3663,9 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, close(p[0]); p[0] = -1; + euid = geteuid(); + egid = getegid(); + /* Find container root. */ lxc_list_for_each(it, &conf->id_map) { map = it->elem; @@ -3678,6 +3681,12 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, 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) @@ -3686,6 +3695,12 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, 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. */ @@ -3699,16 +3714,11 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, goto on_error; } - host_uid_map = container_root_uid; - host_gid_map = container_root_gid; - /* Check whether the {g,u}id of the user has a mapping. */ - euid = geteuid(); - egid = getegid(); - if (euid != container_root_uid->hostid) + if (!host_uid_map) host_uid_map = idmap_add(conf, euid, ID_TYPE_UID); - if (egid != container_root_gid->hostid) + if (!host_gid_map) host_gid_map = idmap_add(conf, egid, ID_TYPE_GID); if (!host_uid_map) { -- 2.47.2