]> git.proxmox.com Git - mirror_lxc.git/commitdiff
conf: fix userns_exec_1()
authorChristian Brauner <christian.brauner@ubuntu.com>
Tue, 5 Sep 2017 15:43:31 +0000 (17:43 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 5 Sep 2017 15:43:31 +0000 (17:43 +0200)
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 <pid> 0 999 999
    newgidmap <pid> 0 999 1000000000

since all required mappings are present. Due to the buggy pointer comparisons
what happened was:

    newuidmap <pid> 0 999 999 0 999 999
    newgidmap <pid> 0 999 1000000000 0 999 1000000000

Let's fix this.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c

index 148d5b6e03b887bcff5f7c584d8aed2baa377237..6e5af200c1f59d41f583e780e9f69a702aa95eb9 100644 (file)
@@ -3682,6 +3682,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;
@@ -3697,6 +3700,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)
@@ -3705,6 +3714,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. */
@@ -3718,16 +3733,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) {