]> git.ipfire.org Git - thirdparty/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)
committerStéphane Graber <stgraber@ubuntu.com>
Sun, 10 Sep 2017 18:12:42 +0000 (14:12 -0400)
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 476073e961aacc830edb0481125fa334c5ced4f4..fd74a66b311bae4de74b99f040c34d86e8a380c8 100644 (file)
@@ -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) {