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, ...@@ -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 * Allocate a new {g,u}id mapping for the given {g,u}id. Re-use an already
* existing one or establish a new one. * existing one or establish a new one.
*/ */
static struct lxc_list *idmap_add_id(struct lxc_conf *conf, uid_t uid, static struct id_map *idmap_add(struct lxc_conf *conf, uid_t id, enum idtype type)
gid_t gid)
{ {
int hostuid_mapped, hostgid_mapped; int hostid_mapped;
struct id_map *hostuid_idmap, *hostgid_idmap;
struct id_map *entry = NULL; 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); /* Reuse existing mapping. */
hostgid_idmap = mapped_hostid_entry(gid, conf, ID_TYPE_GID); entry = mapped_hostid_entry(conf, id, type);
if (entry)
/* Allocate new {g,u}id map list. */ return entry;
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;
tmp->elem = entry; /* Find new mapping. */
entry->idtype = ID_TYPE_UID; hostid_mapped = find_unmapped_nsid(conf, type);
entry->nsid = hostuid_mapped; if (hostid_mapped < 0) {
entry->hostid = (unsigned long)uid; DEBUG("failed to find free mapping for id %d", id);
entry->range = 1; return NULL;
DEBUG("adding uid mapping: nsid %lu hostid %lu range %lu",
entry->nsid, entry->hostid, entry->range);
} }
lxc_list_add_tail(new, tmp);
entry = NULL;
tmp = NULL;
tmp = malloc(sizeof(*tmp)); entry = malloc(sizeof(*entry));
if (!tmp) if (!entry)
goto on_error; return NULL;
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);
return new; entry->idtype = type;
entry->nsid = hostid_mapped;
entry->hostid = (unsigned long)id;
entry->range = 1;
on_error: return entry;
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;
} }
/* Run a function in a new user namespace. /* 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) ...@@ -4818,7 +4768,8 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data)
char c = '1'; char c = '1';
int ret = -1; int ret = -1;
struct lxc_list *idmap = NULL, *tmplist = NULL; 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); ret = pipe(p);
if (ret < 0) { if (ret < 0) {
...@@ -4879,29 +4830,71 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data) ...@@ -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. */ /* Check whether the {g,u}id of the user has a mapping. */
euid = geteuid(); euid = geteuid();
egid = getegid(); egid = getegid();
idmap = idmap_add_id(conf, euid, egid); if (euid == container_root_uid->hostid)
if (!idmap) { host_uid_map = container_root_uid;
ERROR("failed to prepare id mapping for uid %d and gid %d", else
euid, egid); 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; 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. */ /* Add container root to the map. */
tmplist = malloc(sizeof(*tmplist)); tmplist = malloc(sizeof(*tmplist));
if (!tmplist) if (!tmplist)
goto on_error; goto on_error;
lxc_list_add_elem(tmplist, container_root_uid); lxc_list_add_elem(tmplist, container_root_uid);
lxc_list_add_tail(idmap, tmplist); 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)); tmplist = malloc(sizeof(*tmplist));
if (!tmplist) if (!tmplist)
goto on_error; goto on_error;
lxc_list_add_elem(tmplist, container_root_gid); lxc_list_add_elem(tmplist, container_root_gid);
lxc_list_add_tail(idmap, tmplist); 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 || if (lxc_log_get_level() == LXC_LOG_PRIORITY_TRACE ||
conf->loglevel == LXC_LOG_PRIORITY_TRACE) { conf->loglevel == LXC_LOG_PRIORITY_TRACE) {
...@@ -4937,6 +4930,8 @@ on_error: ...@@ -4937,6 +4930,8 @@ on_error:
lxc_free_idmap(idmap); lxc_free_idmap(idmap);
free(container_root_uid); free(container_root_uid);
free(container_root_gid); free(container_root_gid);
free(host_uid_map);
free(host_gid_map);
if (p[0] != -1) if (p[0] != -1)
close(p[0]); 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