Quoting Dwight Engen (dwight.en...@oracle.com): > The kernel requires a single atomic write for setting the /proc > idmap files. We were calling write(2) more than once when multiple > ranges were configured so instead build a buffer to pass in one write(2) > call. > > Change id types to unsigned long to handle large id mappings gracefully. > > Fix max id in example comment. > > Signed-off-by: Dwight Engen <dwight.en...@oracle.com>
I'm really not sure that was intended, but I see it is in fact the case. Thanks Dwight :) Acked-by: Serge Hallyn <serge.hal...@ubuntu.com> > --- > src/lxc/conf.c | 34 ++++++++++++++++++++++++++++------ > src/lxc/conf.h | 16 ++++++++-------- > src/lxc/confile.c | 6 +++--- > 3 files changed, 39 insertions(+), 17 deletions(-) > > diff --git a/src/lxc/conf.c b/src/lxc/conf.c > index e2abc72..9700c7a 100644 > --- a/src/lxc/conf.c > +++ b/src/lxc/conf.c > @@ -2447,7 +2447,8 @@ int lxc_assign_network(struct lxc_list *network, pid_t > pid) > return 0; > } > > -static int add_id_mapping(enum idtype idtype, pid_t pid, uid_t ns_start, > uid_t host_start, int range) > +static int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, > + size_t buf_size) > { > char path[PATH_MAX]; > int ret, closeret; > @@ -2463,7 +2464,7 @@ static int add_id_mapping(enum idtype idtype, pid_t > pid, uid_t ns_start, uid_t h > perror("open"); > return -EINVAL; > } > - ret = fprintf(f, "%d %d %d", ns_start, host_start, range); > + ret = fwrite(buf, buf_size, 1, f); > if (ret < 0) > SYSERROR("writing id mapping"); > closeret = fclose(f); > @@ -2477,13 +2478,34 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) > struct lxc_list *iterator; > struct id_map *map; > int ret = 0; > - > - lxc_list_for_each(iterator, idmap) { > - map = iterator->elem; > - ret = add_id_mapping(map->idtype, pid, map->nsid, map->hostid, > map->range); > + char *buf,*pos; > + enum idtype type; > + > + /* The kernel only takes <= 4k for writes to /proc/<nr>/[ug]id_map */ > + buf = pos = malloc(4096); > + if (!buf) > + return -ENOMEM; > + > + for(type = ID_TYPE_UID; type <= ID_TYPE_GID; type++) { > + int left,fill; > + lxc_list_for_each(iterator, idmap) { > + map = iterator->elem; > + if (map->idtype == type) { > + left = 4096 - (pos - buf); > + fill = snprintf(pos, left, "%lu %lu %lu\n", > + map->nsid, map->hostid, map->range); > + if (fill <= 0 || fill >= left) > + SYSERROR("snprintf failed, too many > mappings"); > + pos += fill; > + } > + } > + ret = write_id_mapping(type, pid, buf, pos-buf); > if (ret) > break; > + pos = buf; > } > + > + free(buf); > return ret; > } > > diff --git a/src/lxc/conf.h b/src/lxc/conf.h > index f20fb2f..cc7961a 100644 > --- a/src/lxc/conf.h > +++ b/src/lxc/conf.h > @@ -149,17 +149,17 @@ enum idtype { > > /* > * id_map is an id map entry. Form in confile is: > - * lxc.id_map = U 9800 0 100 > - * lxc.id_map = U 9900 1000 100 > - * lxc.id_map = G 9800 0 100 > - * lxc.id_map = G 9900 1000 100 > - * meaning the container can use uids and gids 0-100 and 1000-1100, > - * with uid 0 mapping to uid 9800 on the host, and gid 1000 to > - * gid 9900 on the host. > + * lxc.id_map = u 0 9800 100 > + * lxc.id_map = u 1000 9900 100 > + * lxc.id_map = g 0 9800 100 > + * lxc.id_map = g 1000 9900 100 > + * meaning the container can use uids and gids 0-99 and 1000-1099, > + * with [ug]id 0 mapping to [ug]id 9800 on the host, and [ug]id 1000 to > + * [ug]id 9900 on the host. > */ > struct id_map { > enum idtype idtype; > - int hostid, nsid, range; > + unsigned long hostid, nsid, range; > }; > > /* > diff --git a/src/lxc/confile.c b/src/lxc/confile.c > index 59cedef..0b1fd51 100644 > --- a/src/lxc/confile.c > +++ b/src/lxc/confile.c > @@ -1024,7 +1024,7 @@ static int config_idmap(const char *key, const char > *value, struct lxc_conf *lxc > char *subkey; > struct lxc_list *idmaplist = NULL; > struct id_map *idmap = NULL; > - int hostid, nsid, range; > + unsigned long hostid, nsid, range; > char type; > int ret; > > @@ -1049,10 +1049,10 @@ static int config_idmap(const char *key, const char > *value, struct lxc_conf *lxc > > lxc_list_add_tail(&lxc_conf->id_map, idmaplist); > > - ret = sscanf(value, "%c %d %d %d", &type, &nsid, &hostid, &range); > + ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range); > if (ret != 4) > goto out; > - INFO("read uid map: type %c nsid %d hostid %d range %d", type, nsid, > hostid, range); > + INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, > hostid, range); > if (type == 'u') > idmap->idtype = ID_TYPE_UID; > else if (type == 'g') > -- > 1.7.12.3 > > > ------------------------------------------------------------------------------ > Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester > Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the > endpoint security space. For insight on selecting the right partner to > tackle endpoint security challenges, access the full report. > http://p.sf.net/sfu/symantec-dev2dev > _______________________________________________ > Lxc-devel mailing list > Lxc-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lxc-devel ------------------------------------------------------------------------------ Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the endpoint security space. For insight on selecting the right partner to tackle endpoint security challenges, access the full report. http://p.sf.net/sfu/symantec-dev2dev _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel