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();
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
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,
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;
}
/*