conf: rework userns_exec_1()

This also fixes a bug where we caused a double mapping, when the {u,g}id for the user was mapped to container root {g,u}id. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 339efad9
......@@ -4717,83 +4717,33 @@ static struct id_map *mapped_hostid_entry(struct lxc_conf *conf, unsigned id,
* Allocate a new {g,u}id mapping for the given {g,u}id. Re-use an already
* existing one or establish a new one.
*/
static struct lxc_list *idmap_add_id(struct lxc_conf *conf, uid_t uid,
gid_t gid)
static struct id_map *idmap_add(struct lxc_conf *conf, uid_t id, enum idtype type)
{
int hostuid_mapped, hostgid_mapped;
struct id_map *hostuid_idmap, *hostgid_idmap;
int hostid_mapped;
struct id_map *entry = NULL;
struct lxc_list *new = NULL;
struct lxc_list *tmp = NULL;
hostuid_idmap = mapped_hostid_entry(uid, conf, ID_TYPE_UID);
hostgid_idmap = mapped_hostid_entry(gid, conf, ID_TYPE_GID);
/* Allocate new {g,u}id map list. */
new = malloc(sizeof(*new));
if (!new)
goto on_error;
lxc_list_init(new);
tmp = malloc(sizeof(*tmp));
if (!tmp)
goto on_error;
entry = hostuid_idmap;
if (!hostuid_idmap) {
hostuid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID);
if (hostuid_mapped < 0)
goto on_error;
entry = malloc(sizeof(*entry));
if (!entry)
goto on_error;
/* Reuse existing mapping. */
entry = mapped_hostid_entry(conf, id, type);
if (entry)
return entry;
tmp->elem = entry;
entry->idtype = ID_TYPE_UID;
entry->nsid = hostuid_mapped;
entry->hostid = (unsigned long)uid;
entry->range = 1;
DEBUG("adding uid mapping: nsid %lu hostid %lu range %lu",
entry->nsid, entry->hostid, entry->range);
/* Find new mapping. */
hostid_mapped = find_unmapped_nsid(conf, type);
if (hostid_mapped < 0) {
DEBUG("failed to find free mapping for id %d", id);
return NULL;
}
lxc_list_add_tail(new, tmp);
entry = NULL;
tmp = NULL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
goto on_error;
entry = hostgid_idmap;
if (!hostgid_idmap) {
hostgid_mapped = find_unmapped_nsuid(conf, ID_TYPE_GID);
if (hostgid_mapped < 0)
goto on_error;
entry = malloc(sizeof(*entry));
if (!entry)
goto on_error;
tmp->elem = entry;
entry->idtype = ID_TYPE_GID;
entry->nsid = hostgid_mapped;
entry->hostid = (unsigned long)gid;
entry->range = 1;
DEBUG("adding gid mapping: nsid %lu hostid %lu range %lu",
entry->nsid, entry->hostid, entry->range);
}
lxc_list_add_tail(new, tmp);
entry = malloc(sizeof(*entry));
if (!entry)
return NULL;
return new;
entry->idtype = type;
entry->nsid = hostid_mapped;
entry->hostid = (unsigned long)id;
entry->range = 1;
on_error:
ERROR("failed to allocate memory for new id map");
if (new)
lxc_free_idmap(new);
free(new);
free(tmp);
if (entry)
free(entry);
return NULL;
return entry;
}
/* Run a function in a new user namespace.
......@@ -4818,7 +4768,8 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data)
char c = '1';
int ret = -1;
struct lxc_list *idmap = NULL, *tmplist = NULL;
struct id_map *container_root_uid = NULL, *container_root_gid = NULL;
struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
*host_uid_map = NULL, *host_gid_map = NULL;
ret = pipe(p);
if (ret < 0) {
......@@ -4879,29 +4830,71 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data)
/* Check whether the {g,u}id of the user has a mapping. */
euid = geteuid();
egid = getegid();
idmap = idmap_add_id(conf, euid, egid);
if (!idmap) {
ERROR("failed to prepare id mapping for uid %d and gid %d",
euid, egid);
if (euid == container_root_uid->hostid)
host_uid_map = container_root_uid;
else
host_uid_map = idmap_add(conf, euid, ID_TYPE_UID);
if (egid == container_root_gid->hostid)
host_gid_map = container_root_gid;
else
host_gid_map = idmap_add(conf, egid, ID_TYPE_GID);
if (!host_uid_map) {
DEBUG("failed to find mapping for uid %d", euid);
goto on_error;
}
if (!host_gid_map) {
DEBUG("failed to find mapping for gid %d", egid);
goto on_error;
}
/* Allocate new {g,u}id map list. */
idmap = malloc(sizeof(*idmap));
if (!idmap)
goto on_error;
lxc_list_init(idmap);
/* Add container root to the map. */
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, container_root_uid);
lxc_list_add_tail(idmap, tmplist);
/* idmap will now keep track of that memory. */
container_root_uid = NULL;
if (host_uid_map != container_root_uid) {
/* idmap will now keep track of that memory. */
container_root_uid = NULL;
/* Add container root to the map. */
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, host_uid_map);
lxc_list_add_tail(idmap, tmplist);
/* idmap will now keep track of that memory. */
host_uid_map = NULL;
}
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, container_root_gid);
lxc_list_add_tail(idmap, tmplist);
/* idmap will now keep track of that memory. */
container_root_gid = NULL;
if (host_gid_map != container_root_gid) {
/* idmap will now keep track of that memory. */
container_root_gid = NULL;
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, host_gid_map);
lxc_list_add_tail(idmap, tmplist);
/* idmap will now keep track of that memory. */
host_gid_map = NULL;
}
if (lxc_log_get_level() == LXC_LOG_PRIORITY_TRACE ||
conf->loglevel == LXC_LOG_PRIORITY_TRACE) {
......@@ -4937,6 +4930,8 @@ on_error:
lxc_free_idmap(idmap);
free(container_root_uid);
free(container_root_gid);
free(host_uid_map);
free(host_gid_map);
if (p[0] != -1)
close(p[0]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment