]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: rework lxc_map_ids()
authorChristian Brauner <christian.brauner@ubuntu.com>
Sun, 28 May 2017 13:10:35 +0000 (15:10 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 30 May 2017 07:11:47 +0000 (09:11 +0200)
Especially, in case the new{g,u}idmap is used we should try to gather
std{err,out} on error to better debug what is going on.

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

index 0efd70c94f3913de6efc1ebea7b72a6cba34da00..35501ee4dc5b914fcb2dc17e5004d7375e49472c 100644 (file)
@@ -3473,16 +3473,35 @@ cleanup:
        return fret;
 }
 
+int lxc_map_ids_exec_wrapper(void *args)
+{
+       execl("/bin/sh", "sh", "-c", (char *)args, (char *)NULL);
+       return -1;
+}
+
 int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
 {
        struct id_map *map;
        struct lxc_list *iterator;
        enum idtype type;
+       char u_or_g;
        char *pos;
-       int euid;
-       int ret = 0, use_shadow = 0;
-       int uidmap = 0, gidmap = 0;
-       char *buf = NULL;
+       int euid, fill, left;
+       char cmd_output[MAXPATHLEN];
+       /* strlen("new@idmap") = 9
+        * +
+        * strlen(" ") = 1
+        * +
+        * LXC_NUMSTRLEN64
+        * +
+        * strlen(" ") = 1
+        *
+        * We add some additional space to make sure that we really have
+        * LXC_IDMAPLEN bytes available for our the {g,u]id mapping.
+        */
+       char mapbuf[9 + 1 + LXC_NUMSTRLEN64 + 1 + LXC_IDMAPLEN] = {0};
+       int ret = 0, uidmap = 0, gidmap = 0;
+       bool use_shadow = false, had_entry = false;
 
        euid = geteuid();
 
@@ -3507,17 +3526,12 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
                return -1;
        }
 
-       for (type = ID_TYPE_UID; type <= ID_TYPE_GID; type++) {
-               int left, fill;
-               bool had_entry = false;
-               if (!buf) {
-                       buf = pos = malloc(LXC_IDMAPLEN);
-                       if (!buf)
-                               return -ENOMEM;
-               }
-               pos = buf;
+       for (type = ID_TYPE_UID, u_or_g = 'u'; type <= ID_TYPE_GID;
+            type++, u_or_g = 'g') {
+               pos = mapbuf;
+
                if (use_shadow)
-                       pos += sprintf(buf, "new%cidmap %d", type == ID_TYPE_UID ? 'u' : 'g', pid);
+                       pos += sprintf(mapbuf, "new%cidmap %d", u_or_g, pid);
 
                lxc_list_for_each(iterator, idmap) {
                        /* The kernel only takes <= 4k for writes to
@@ -3529,7 +3543,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
 
                        had_entry = true;
 
-                       left = LXC_IDMAPLEN - (pos - buf);
+                       left = LXC_IDMAPLEN - (pos - mapbuf);
                        fill = snprintf(pos, left, "%s%lu %lu %lu%s",
                                        use_shadow ? " " : "", map->nsid,
                                        map->hostid, map->range,
@@ -3542,22 +3556,28 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
                if (!had_entry)
                        continue;
 
-               if (!use_shadow) {
-                       ret = write_id_mapping(type, pid, buf, pos - buf);
+               /* Try to catch the ouput of new{g,u}idmap to make debugging
+                * easier.
+                */
+               if (use_shadow) {
+                       ret = run_command(cmd_output, sizeof(cmd_output),
+                                         lxc_map_ids_exec_wrapper,
+                                         (void *)mapbuf);
+                       if (ret < 0) {
+                               ERROR("new%cidmap failed to write mapping: %s",
+                                     u_or_g, cmd_output);
+                               return -1;
+                       }
                } else {
-                       left = LXC_IDMAPLEN - (pos - buf);
-                       fill = snprintf(pos, left, "\n");
-                       if (fill <= 0 || fill >= left)
-                               SYSERROR("Too many {g,u}id mappings defined.");
-                       pos += fill;
-                       ret = system(buf);
+                       ret = write_id_mapping(type, pid, mapbuf, pos - mapbuf);
+                       if (ret < 0)
+                               return -1;
                }
-               if (ret)
-                       break;
+
+               memset(mapbuf, 0, sizeof(mapbuf));
        }
 
-       free(buf);
-       return ret;
+       return 0;
 }
 
 /*