mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 00:09:52 +00:00
conf: port id_map to new list type
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
parent
c9dbb8edf9
commit
0589d744f6
@ -575,7 +575,7 @@ __cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops,
|
||||
if (ret < 0)
|
||||
WARN("Failed to detach bpf program from cgroup");
|
||||
|
||||
if (!lxc_list_empty(&handler->conf->id_map)) {
|
||||
if (!list_empty(&handler->conf->id_map)) {
|
||||
struct generic_userns_exec_data wrap = {
|
||||
.conf = handler->conf,
|
||||
.path_prune = ops->container_limit_cgroup,
|
||||
@ -1363,7 +1363,7 @@ __cgfsng_ops static bool cgfsng_chown(struct cgroup_ops *ops,
|
||||
if (!conf)
|
||||
return ret_set_errno(false, EINVAL);
|
||||
|
||||
if (lxc_list_empty(&conf->id_map))
|
||||
if (list_empty(&conf->id_map))
|
||||
return true;
|
||||
|
||||
wrap.origuid = geteuid();
|
||||
@ -2289,7 +2289,7 @@ static int __cg_unified_attach(const struct hierarchy *h,
|
||||
if (unified_fd < 0)
|
||||
return ret_errno(EBADF);
|
||||
|
||||
if (!lxc_list_empty(&conf->id_map)) {
|
||||
if (!list_empty(&conf->id_map)) {
|
||||
struct userns_exec_unified_attach_data args = {
|
||||
.conf = conf,
|
||||
.unified_fd = unified_fd,
|
||||
@ -3344,7 +3344,7 @@ static int initialize_cgroups(struct cgroup_ops *ops, struct lxc_conf *conf)
|
||||
*/
|
||||
ops->dfd_mnt = dfd;
|
||||
|
||||
ret = __initialize_cgroups(ops, conf->cgroup_meta.relative, !lxc_list_empty(&conf->id_map));
|
||||
ret = __initialize_cgroups(ops, conf->cgroup_meta.relative, !list_empty(&conf->id_map));
|
||||
if (ret < 0)
|
||||
return syserror_ret(ret, "Failed to initialize cgroups");
|
||||
|
||||
@ -3421,7 +3421,7 @@ static int __unified_attach_fd(const struct lxc_conf *conf, int fd_unified, pid_
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!lxc_list_empty(&conf->id_map)) {
|
||||
if (!list_empty(&conf->id_map)) {
|
||||
struct userns_exec_unified_attach_data args = {
|
||||
.conf = conf,
|
||||
.unified_fd = fd_unified,
|
||||
|
@ -114,11 +114,10 @@ static int do_child(void *vargv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct lxc_list active_map;
|
||||
static LIST_HEAD(active_map);
|
||||
|
||||
static int add_map_entry(long host_id, long ns_id, long range, int which)
|
||||
{
|
||||
struct lxc_list *tmp = NULL;
|
||||
struct id_map *newmap;
|
||||
|
||||
newmap = malloc(sizeof(*newmap));
|
||||
@ -129,14 +128,8 @@ static int add_map_entry(long host_id, long ns_id, long range, int which)
|
||||
newmap->nsid = ns_id;
|
||||
newmap->range = range;
|
||||
newmap->idtype = which;
|
||||
tmp = malloc(sizeof(*tmp));
|
||||
if (!tmp) {
|
||||
free(newmap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp->elem = newmap;
|
||||
lxc_list_add_tail(&active_map, tmp);
|
||||
list_add_tail(&newmap->head, &active_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -280,11 +273,9 @@ static bool do_map_self(void)
|
||||
{
|
||||
struct id_map *map;
|
||||
long nsuid = 0, nsgid = 0;
|
||||
struct lxc_list *tmp = NULL;
|
||||
int ret;
|
||||
|
||||
lxc_list_for_each(tmp, &active_map) {
|
||||
map = tmp->elem;
|
||||
list_for_each_entry(map, &active_map, head) {
|
||||
if (map->idtype == ID_TYPE_UID) {
|
||||
if (is_in_ns_range(nsuid, map))
|
||||
nsuid += map->range;
|
||||
@ -336,8 +327,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
lxc_list_init(&active_map);
|
||||
|
||||
while ((c = getopt(argc, argv, "m:hs")) != EOF) {
|
||||
switch (c) {
|
||||
case 'm':
|
||||
@ -359,7 +348,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
};
|
||||
|
||||
if (lxc_list_empty(&active_map)) {
|
||||
if (list_empty(&active_map)) {
|
||||
ret = find_default_map();
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to find subuid or subgid allocation\n");
|
||||
|
242
src/lxc/conf.c
242
src/lxc/conf.c
@ -619,7 +619,7 @@ int lxc_rootfs_prepare_parent(struct lxc_handler *handler)
|
||||
int ret;
|
||||
const char *path_source;
|
||||
|
||||
if (lxc_list_empty(&handler->conf->id_map))
|
||||
if (list_empty(&handler->conf->id_map))
|
||||
return 0;
|
||||
|
||||
if (is_empty_string(rootfs->mnt_opts.userns_path))
|
||||
@ -1616,7 +1616,6 @@ static const struct id_map *find_mapped_nsid_entry(const struct lxc_conf *conf,
|
||||
unsigned id,
|
||||
enum idtype idtype)
|
||||
{
|
||||
struct lxc_list *it;
|
||||
struct id_map *map;
|
||||
struct id_map *retmap = NULL;
|
||||
|
||||
@ -1629,8 +1628,7 @@ static const struct id_map *find_mapped_nsid_entry(const struct lxc_conf *conf,
|
||||
return conf->root_nsgid_map;
|
||||
}
|
||||
|
||||
lxc_list_for_each(it, &conf->id_map) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, &conf->id_map, head) {
|
||||
if (map->idtype != idtype)
|
||||
continue;
|
||||
|
||||
@ -3387,7 +3385,7 @@ struct lxc_conf *lxc_conf_init(void)
|
||||
lxc_list_init(&new->mount_list);
|
||||
lxc_list_init(&new->caps);
|
||||
lxc_list_init(&new->keepcaps);
|
||||
lxc_list_init(&new->id_map);
|
||||
INIT_LIST_HEAD(&new->id_map);
|
||||
new->root_nsuid_map = NULL;
|
||||
new->root_nsgid_map = NULL;
|
||||
lxc_list_init(&new->includes);
|
||||
@ -3528,24 +3526,22 @@ static int lxc_map_ids_exec_wrapper(void *args)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct id_map *find_mapped_hostid_entry(const struct lxc_list *idmap,
|
||||
static struct id_map *find_mapped_hostid_entry(const struct list_head *idmap,
|
||||
unsigned id, enum idtype idtype);
|
||||
|
||||
int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
||||
int lxc_map_ids(struct list_head *idmap, pid_t pid)
|
||||
{
|
||||
int fill, left;
|
||||
int hostuid, hostgid, fill, left;
|
||||
char u_or_g;
|
||||
char *pos;
|
||||
char cmd_output[PATH_MAX];
|
||||
struct id_map *map;
|
||||
struct lxc_list *iterator;
|
||||
enum idtype type;
|
||||
int ret = 0, gidmap = 0, uidmap = 0;
|
||||
char mapbuf[STRLITERALLEN("new@idmap") + STRLITERALLEN(" ") +
|
||||
INTTYPE_TO_STRLEN(pid_t) + STRLITERALLEN(" ") +
|
||||
LXC_IDMAPLEN] = {0};
|
||||
bool had_entry = false, maps_host_root = false, use_shadow = false;
|
||||
int hostuid, hostgid;
|
||||
|
||||
hostuid = geteuid();
|
||||
hostgid = getegid();
|
||||
@ -3595,10 +3591,9 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
||||
/* Check if we really need to use newuidmap and newgidmap.
|
||||
* If the user is only remapping their own {g,u}id, we don't need it.
|
||||
*/
|
||||
if (use_shadow && lxc_list_len(idmap) == 2) {
|
||||
if (use_shadow && list_len(idmap) == 2) {
|
||||
use_shadow = false;
|
||||
lxc_list_for_each(iterator, idmap) {
|
||||
map = iterator->elem;
|
||||
list_for_each_entry(map, idmap, head) {
|
||||
if (map->idtype == ID_TYPE_UID && map->range == 1 &&
|
||||
map->nsid == hostuid && map->hostid == hostuid)
|
||||
continue;
|
||||
@ -3617,8 +3612,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
||||
if (use_shadow)
|
||||
pos += sprintf(mapbuf, "new%cidmap %d", u_or_g, pid);
|
||||
|
||||
lxc_list_for_each(iterator, idmap) {
|
||||
map = iterator->elem;
|
||||
list_for_each_entry(map, idmap, head) {
|
||||
if (map->idtype != type)
|
||||
continue;
|
||||
|
||||
@ -3672,15 +3666,13 @@ static id_t get_mapped_rootid(const struct lxc_conf *conf, enum idtype idtype)
|
||||
{
|
||||
unsigned nsid;
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
|
||||
if (idtype == ID_TYPE_UID)
|
||||
nsid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid;
|
||||
else
|
||||
nsid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid;
|
||||
|
||||
lxc_list_for_each (it, &conf->id_map) {
|
||||
map = it->elem;
|
||||
list_for_each_entry (map, &conf->id_map, head) {
|
||||
if (map->idtype != idtype)
|
||||
continue;
|
||||
if (map->nsid != nsid)
|
||||
@ -3697,10 +3689,8 @@ static id_t get_mapped_rootid(const struct lxc_conf *conf, enum idtype idtype)
|
||||
int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype)
|
||||
{
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
|
||||
lxc_list_for_each (it, &conf->id_map) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, &conf->id_map, head) {
|
||||
if (map->idtype != idtype)
|
||||
continue;
|
||||
|
||||
@ -3714,12 +3704,10 @@ int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype)
|
||||
int find_unmapped_nsid(const struct lxc_conf *conf, enum idtype idtype)
|
||||
{
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
unsigned int freeid = 0;
|
||||
|
||||
again:
|
||||
lxc_list_for_each (it, &conf->id_map) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, &conf->id_map, head) {
|
||||
if (map->idtype != idtype)
|
||||
continue;
|
||||
|
||||
@ -4071,7 +4059,7 @@ static int lxc_rootfs_prepare_child(struct lxc_handler *handler)
|
||||
int dfd_idmapped = -EBADF;
|
||||
int ret;
|
||||
|
||||
if (lxc_list_empty(&handler->conf->id_map))
|
||||
if (list_empty(&handler->conf->id_map))
|
||||
return 0;
|
||||
|
||||
if (is_empty_string(rootfs->mnt_opts.userns_path))
|
||||
@ -4487,27 +4475,25 @@ int lxc_clear_config_caps(struct lxc_conf *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxc_free_idmap(struct lxc_list *id_map)
|
||||
static int lxc_free_idmap(struct list_head *id_map)
|
||||
{
|
||||
struct lxc_list *it, *next;
|
||||
struct id_map *map, *nmap;
|
||||
|
||||
lxc_list_for_each_safe(it, id_map, next) {
|
||||
lxc_list_del(it);
|
||||
free(it->elem);
|
||||
free(it);
|
||||
list_for_each_entry_safe(map, nmap, id_map, head) {
|
||||
list_del(&map->head);
|
||||
free(map);
|
||||
}
|
||||
|
||||
lxc_list_init(id_map);
|
||||
INIT_LIST_HEAD(id_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __lxc_free_idmap(struct lxc_list *id_map)
|
||||
static int __lxc_free_idmap(struct list_head *id_map)
|
||||
{
|
||||
lxc_free_idmap(id_map);
|
||||
free(id_map);
|
||||
return 0;
|
||||
}
|
||||
define_cleanup_function(struct lxc_list *, __lxc_free_idmap);
|
||||
define_cleanup_function(struct list_head *, __lxc_free_idmap);
|
||||
|
||||
int lxc_clear_idmaps(struct lxc_conf *c)
|
||||
{
|
||||
@ -4905,15 +4891,13 @@ static struct id_map *mapped_nsid_add(const struct lxc_conf *conf, unsigned id,
|
||||
return retmap;
|
||||
}
|
||||
|
||||
static struct id_map *find_mapped_hostid_entry(const struct lxc_list *idmap,
|
||||
static struct id_map *find_mapped_hostid_entry(const struct list_head *idmap,
|
||||
unsigned id, enum idtype idtype)
|
||||
{
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
struct id_map *retmap = NULL;
|
||||
struct id_map *map;
|
||||
|
||||
lxc_list_for_each (it, idmap) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, idmap, head) {
|
||||
if (map->idtype != idtype)
|
||||
continue;
|
||||
|
||||
@ -4959,22 +4943,20 @@ static struct id_map *mapped_hostid_add(const struct lxc_conf *conf, uid_t id,
|
||||
return move_ptr(entry);
|
||||
}
|
||||
|
||||
static struct lxc_list *get_minimal_idmap(const struct lxc_conf *conf,
|
||||
uid_t *resuid, gid_t *resgid)
|
||||
static int get_minimal_idmap(const struct lxc_conf *conf, uid_t *resuid,
|
||||
gid_t *resgid, struct list_head *head_ret)
|
||||
{
|
||||
__do_free struct id_map *container_root_uid = NULL,
|
||||
*container_root_gid = NULL,
|
||||
*host_uid_map = NULL, *host_gid_map = NULL;
|
||||
__do_free struct lxc_list *idmap = NULL;
|
||||
uid_t euid, egid;
|
||||
uid_t nsuid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid;
|
||||
gid_t nsgid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid;
|
||||
struct lxc_list *tmplist = NULL;
|
||||
|
||||
/* Find container root mappings. */
|
||||
container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID);
|
||||
if (!container_root_uid)
|
||||
return log_debug(NULL, "Failed to find mapping for namespace uid %d", 0);
|
||||
return sysdebug("Failed to find mapping for namespace uid %d", 0);
|
||||
euid = geteuid();
|
||||
if (euid >= container_root_uid->hostid &&
|
||||
euid < (container_root_uid->hostid + container_root_uid->range))
|
||||
@ -4982,7 +4964,7 @@ static struct lxc_list *get_minimal_idmap(const struct lxc_conf *conf,
|
||||
|
||||
container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID);
|
||||
if (!container_root_gid)
|
||||
return log_debug(NULL, "Failed to find mapping for namespace gid %d", 0);
|
||||
return sysdebug("Failed to find mapping for namespace gid %d", 0);
|
||||
egid = getegid();
|
||||
if (egid >= container_root_gid->hostid &&
|
||||
egid < (container_root_gid->hostid + container_root_gid->range))
|
||||
@ -4992,50 +4974,31 @@ static struct lxc_list *get_minimal_idmap(const struct lxc_conf *conf,
|
||||
if (!host_uid_map)
|
||||
host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID);
|
||||
if (!host_uid_map)
|
||||
return log_debug(NULL, "Failed to find mapping for uid %d", euid);
|
||||
return sysdebug("Failed to find mapping for uid %d", euid);
|
||||
|
||||
if (!host_gid_map)
|
||||
host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
|
||||
if (!host_gid_map)
|
||||
return log_debug(NULL, "Failed to find mapping for gid %d", egid);
|
||||
return sysdebug("Failed to find mapping for gid %d", egid);
|
||||
|
||||
/* Allocate new {g,u}id map list. */
|
||||
idmap = lxc_list_new();
|
||||
if (!idmap)
|
||||
return NULL;
|
||||
|
||||
/* Add container root to the map. */
|
||||
tmplist = lxc_list_new();
|
||||
if (!tmplist)
|
||||
return NULL;
|
||||
/* idmap will now keep track of that memory. */
|
||||
lxc_list_add_elem(tmplist, move_ptr(host_uid_map));
|
||||
lxc_list_add_tail(idmap, tmplist);
|
||||
list_add_tail(&host_uid_map->head, head_ret);
|
||||
move_ptr(host_uid_map);
|
||||
|
||||
if (container_root_uid) {
|
||||
/* Add container root to the map. */
|
||||
tmplist = lxc_list_new();
|
||||
if (!tmplist)
|
||||
return NULL;
|
||||
/* idmap will now keep track of that memory. */
|
||||
lxc_list_add_elem(tmplist, move_ptr(container_root_uid));
|
||||
lxc_list_add_tail(idmap, tmplist);
|
||||
list_add_tail(&container_root_uid->head, head_ret);
|
||||
move_ptr(container_root_uid);
|
||||
}
|
||||
|
||||
tmplist = lxc_list_new();
|
||||
if (!tmplist)
|
||||
return NULL;
|
||||
/* idmap will now keep track of that memory. */
|
||||
lxc_list_add_elem(tmplist, move_ptr(host_gid_map));
|
||||
lxc_list_add_tail(idmap, tmplist);
|
||||
list_add_tail(&host_gid_map->head, head_ret);
|
||||
move_ptr(host_gid_map);
|
||||
|
||||
if (container_root_gid) {
|
||||
tmplist = lxc_list_new();
|
||||
if (!tmplist)
|
||||
return NULL;
|
||||
/* idmap will now keep track of that memory. */
|
||||
lxc_list_add_elem(tmplist, move_ptr(container_root_gid));
|
||||
lxc_list_add_tail(idmap, tmplist);
|
||||
list_add_tail(&container_root_gid->head, head_ret);
|
||||
move_ptr(container_root_gid);
|
||||
}
|
||||
|
||||
TRACE("Allocated minimal idmapping for ns uid %d and ns gid %d", nsuid, nsgid);
|
||||
@ -5044,7 +5007,8 @@ static struct lxc_list *get_minimal_idmap(const struct lxc_conf *conf,
|
||||
*resuid = nsuid;
|
||||
if (resgid)
|
||||
*resgid = nsgid;
|
||||
return move_ptr(idmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5062,7 +5026,8 @@ static struct lxc_list *get_minimal_idmap(const struct lxc_conf *conf,
|
||||
int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
const char *fn_name)
|
||||
{
|
||||
call_cleaner(__lxc_free_idmap) struct lxc_list *idmap = NULL;
|
||||
LIST_HEAD(minimal_idmap);
|
||||
call_cleaner(__lxc_free_idmap) struct list_head *idmap = &minimal_idmap;
|
||||
int ret = -1, status = -1;
|
||||
char c = '1';
|
||||
struct userns_fn_data d = {
|
||||
@ -5076,8 +5041,8 @@ int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
if (!conf)
|
||||
return -EINVAL;
|
||||
|
||||
idmap = get_minimal_idmap(conf, NULL, NULL);
|
||||
if (!idmap)
|
||||
ret = get_minimal_idmap(conf, NULL, NULL, idmap);
|
||||
if (ret)
|
||||
return ret_errno(ENOENT);
|
||||
|
||||
ret = pipe2(pipe_fds, O_CLOEXEC);
|
||||
@ -5098,13 +5063,10 @@ int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
|
||||
if (lxc_log_trace()) {
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
|
||||
lxc_list_for_each(it, idmap) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, idmap, head)
|
||||
TRACE("Establishing %cid mapping for \"%d\" in new user namespace: nsuid %lu - hostid %lu - range %lu",
|
||||
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid, map->nsid, map->hostid, map->range);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up {g,u}id mapping for user namespace of child process. */
|
||||
@ -5138,7 +5100,8 @@ int userns_exec_minimal(const struct lxc_conf *conf,
|
||||
int (*fn_parent)(void *), void *fn_parent_data,
|
||||
int (*fn_child)(void *), void *fn_child_data)
|
||||
{
|
||||
call_cleaner(__lxc_free_idmap) struct lxc_list *idmap = NULL;
|
||||
LIST_HEAD(minimal_idmap);
|
||||
call_cleaner(__lxc_free_idmap) struct list_head *idmap = &minimal_idmap;
|
||||
uid_t resuid = LXC_INVALID_UID;
|
||||
gid_t resgid = LXC_INVALID_GID;
|
||||
char c = '1';
|
||||
@ -5149,8 +5112,8 @@ int userns_exec_minimal(const struct lxc_conf *conf,
|
||||
if (!conf || !fn_child)
|
||||
return ret_errno(EINVAL);
|
||||
|
||||
idmap = get_minimal_idmap(conf, &resuid, &resgid);
|
||||
if (!idmap)
|
||||
ret = get_minimal_idmap(conf, &resuid, &resgid, idmap);
|
||||
if (ret)
|
||||
return ret_errno(ENOENT);
|
||||
|
||||
ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sock_fds);
|
||||
@ -5212,13 +5175,10 @@ int userns_exec_minimal(const struct lxc_conf *conf,
|
||||
|
||||
if (lxc_log_trace()) {
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
|
||||
lxc_list_for_each(it, idmap) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, idmap, head)
|
||||
TRACE("Establishing %cid mapping for \"%d\" in new user namespace: nsuid %lu - hostid %lu - range %lu",
|
||||
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid, map->nsid, map->hostid, map->range);
|
||||
}
|
||||
}
|
||||
|
||||
ret = lxc_read_nointr(sock_fds[1], &c, 1);
|
||||
@ -5260,26 +5220,24 @@ on_error:
|
||||
int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
const char *fn_name)
|
||||
{
|
||||
LIST_HEAD(full_idmap);
|
||||
int ret = -1;
|
||||
char c = '1';
|
||||
struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
|
||||
*host_uid_map = NULL, *host_gid_map = NULL;
|
||||
pid_t pid;
|
||||
uid_t euid, egid;
|
||||
int p[2];
|
||||
struct id_map *map;
|
||||
struct lxc_list *cur;
|
||||
struct userns_fn_data d;
|
||||
int ret = -1;
|
||||
char c = '1';
|
||||
struct lxc_list *idmap = NULL, *tmplist = NULL;
|
||||
struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
|
||||
*host_uid_map = NULL, *host_gid_map = NULL;
|
||||
|
||||
if (!conf)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pipe2(p, O_CLOEXEC);
|
||||
if (ret < 0) {
|
||||
SYSERROR("opening pipe");
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0)
|
||||
return -errno;
|
||||
|
||||
d.fn = fn;
|
||||
d.fn_name = fn_name;
|
||||
d.arg = data;
|
||||
@ -5299,32 +5257,16 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
euid = geteuid();
|
||||
egid = getegid();
|
||||
|
||||
/* Allocate new {g,u}id map list. */
|
||||
idmap = lxc_list_new();
|
||||
if (!idmap)
|
||||
goto on_error;
|
||||
|
||||
/* Find container root. */
|
||||
lxc_list_for_each (cur, &conf->id_map) {
|
||||
struct id_map *tmpmap;
|
||||
list_for_each_entry(map, &conf->id_map, head) {
|
||||
__do_free struct id_map *dup_map = NULL;
|
||||
|
||||
tmplist = lxc_list_new();
|
||||
if (!tmplist)
|
||||
dup_map = memdup(map, sizeof(struct id_map));
|
||||
if (!dup_map)
|
||||
goto on_error;
|
||||
|
||||
tmpmap = zalloc(sizeof(*tmpmap));
|
||||
if (!tmpmap) {
|
||||
free(tmplist);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
memset(tmpmap, 0, sizeof(*tmpmap));
|
||||
memcpy(tmpmap, cur->elem, sizeof(*tmpmap));
|
||||
tmplist->elem = tmpmap;
|
||||
|
||||
lxc_list_add_tail(idmap, tmplist);
|
||||
|
||||
map = cur->elem;
|
||||
list_add_tail(&dup_map->head, &full_idmap);
|
||||
move_ptr(dup_map);
|
||||
|
||||
if (map->idtype == ID_TYPE_UID)
|
||||
if (euid >= map->hostid && euid < map->hostid + map->range)
|
||||
@ -5373,39 +5315,27 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
|
||||
}
|
||||
|
||||
if (host_uid_map && (host_uid_map != container_root_uid)) {
|
||||
/* Add container root to the map. */
|
||||
tmplist = lxc_list_new();
|
||||
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. */
|
||||
list_add_tail(&host_uid_map->head, &full_idmap);
|
||||
move_ptr(host_uid_map);
|
||||
}
|
||||
/* idmap will now keep track of that memory. */
|
||||
host_uid_map = NULL;
|
||||
|
||||
if (host_gid_map && (host_gid_map != container_root_gid)) {
|
||||
tmplist = lxc_list_new();
|
||||
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. */
|
||||
list_add_tail(&host_gid_map->head, &full_idmap);
|
||||
move_ptr(host_gid_map);
|
||||
}
|
||||
/* idmap will now keep track of that memory. */
|
||||
host_gid_map = NULL;
|
||||
|
||||
if (lxc_log_trace()) {
|
||||
lxc_list_for_each (cur, idmap) {
|
||||
map = cur->elem;
|
||||
TRACE("establishing %cid mapping for \"%d\" in new "
|
||||
"user namespace: nsuid %lu - hostid %lu - range "
|
||||
"%lu",
|
||||
list_for_each_entry(map, &full_idmap, head) {
|
||||
TRACE("establishing %cid mapping for \"%d\" in new user namespace: nsuid %lu - hostid %lu - range %lu",
|
||||
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid,
|
||||
map->nsid, map->hostid, map->range);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up {g,u}id mapping for user namespace of child process. */
|
||||
ret = lxc_map_ids(idmap, pid);
|
||||
ret = lxc_map_ids(&full_idmap, pid);
|
||||
if (ret < 0) {
|
||||
ERROR("error setting up {g,u}id mappings for child process \"%d\"", pid);
|
||||
goto on_error;
|
||||
@ -5426,8 +5356,7 @@ on_error:
|
||||
if (pid > 0)
|
||||
ret = wait_for_pid(pid);
|
||||
|
||||
if (idmap)
|
||||
__lxc_free_idmap(idmap);
|
||||
__lxc_free_idmap(&full_idmap);
|
||||
|
||||
if (host_uid_map && (host_uid_map != container_root_uid))
|
||||
free(host_uid_map);
|
||||
@ -5437,12 +5366,11 @@ on_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int add_idmap_entry(struct lxc_list *idmap, enum idtype idtype,
|
||||
static int add_idmap_entry(struct list_head *idmap_list, enum idtype idtype,
|
||||
unsigned long nsid, unsigned long hostid,
|
||||
unsigned long range)
|
||||
{
|
||||
__do_free struct id_map *new_idmap = NULL;
|
||||
__do_free struct lxc_list *new_list = NULL;
|
||||
|
||||
new_idmap = zalloc(sizeof(*new_idmap));
|
||||
if (!new_idmap)
|
||||
@ -5453,12 +5381,8 @@ static int add_idmap_entry(struct lxc_list *idmap, enum idtype idtype,
|
||||
new_idmap->nsid = nsid;
|
||||
new_idmap->range = range;
|
||||
|
||||
new_list = zalloc(sizeof(*new_list));
|
||||
if (!new_list)
|
||||
return ret_errno(ENOMEM);
|
||||
|
||||
new_list->elem = move_ptr(new_idmap);
|
||||
lxc_list_add_tail(idmap, move_ptr(new_list));
|
||||
list_add_tail(&new_idmap->head, idmap_list);
|
||||
move_ptr(new_idmap);
|
||||
|
||||
INFO("Adding id map: type %c nsid %lu hostid %lu range %lu",
|
||||
idtype == ID_TYPE_UID ? 'u' : 'g', nsid, hostid, range);
|
||||
@ -5468,7 +5392,8 @@ static int add_idmap_entry(struct lxc_list *idmap, enum idtype idtype,
|
||||
int userns_exec_mapped_root(const char *path, int path_fd,
|
||||
const struct lxc_conf *conf)
|
||||
{
|
||||
call_cleaner(__lxc_free_idmap) struct lxc_list *idmap = NULL;
|
||||
LIST_HEAD(idmap_list);
|
||||
call_cleaner(__lxc_free_idmap) struct list_head *idmap = &idmap_list;
|
||||
__do_close int fd = -EBADF;
|
||||
int target_fd = -EBADF;
|
||||
char c = '1';
|
||||
@ -5534,10 +5459,6 @@ int userns_exec_mapped_root(const char *path, int path_fd,
|
||||
TRACE("Chowned %d(%s) to -1:%d", target_fd, path, hostgid);
|
||||
}
|
||||
|
||||
idmap = lxc_list_new();
|
||||
if (!idmap)
|
||||
return -ENOMEM;
|
||||
|
||||
/* "u:0:rootuid:1" */
|
||||
ret = add_idmap_entry(idmap, ID_TYPE_UID, 0, container_host_uid, 1);
|
||||
if (ret < 0)
|
||||
@ -5615,13 +5536,10 @@ int userns_exec_mapped_root(const char *path, int path_fd,
|
||||
|
||||
if (lxc_log_trace()) {
|
||||
struct id_map *map;
|
||||
struct lxc_list *it;
|
||||
|
||||
lxc_list_for_each(it, idmap) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, idmap, head)
|
||||
TRACE("Establishing %cid mapping for \"%d\" in new user namespace: nsuid %lu - hostid %lu - range %lu",
|
||||
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid, map->nsid, map->hostid, map->range);
|
||||
}
|
||||
}
|
||||
|
||||
ret = lxc_read_nointr(sock_fds[1], &c, 1);
|
||||
|
@ -181,6 +181,7 @@ define_cleanup_function(struct lxc_proc *, free_lxc_proc);
|
||||
struct id_map {
|
||||
enum idtype idtype;
|
||||
unsigned long hostid, nsid, range;
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
/* Defines the number of tty configured and contains the
|
||||
@ -352,7 +353,7 @@ struct lxc_conf {
|
||||
};
|
||||
|
||||
struct {
|
||||
struct lxc_list id_map;
|
||||
struct list_head id_map;
|
||||
|
||||
/*
|
||||
* Pointer to the idmap entry for the container's root uid in
|
||||
@ -525,7 +526,7 @@ __hidden extern void lxc_storage_put(struct lxc_conf *conf);
|
||||
__hidden extern int lxc_rootfs_init(struct lxc_conf *conf, bool userns);
|
||||
__hidden extern int lxc_rootfs_prepare_parent(struct lxc_handler *handler);
|
||||
__hidden extern int lxc_idmapped_mounts_parent(struct lxc_handler *handler);
|
||||
__hidden extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
|
||||
__hidden extern int lxc_map_ids(struct list_head *idmap, pid_t pid);
|
||||
__hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
|
||||
__hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys);
|
||||
__hidden extern int lxc_clear_config_caps(struct lxc_conf *c);
|
||||
|
@ -2210,7 +2210,6 @@ static int set_config_proc(const char *key, const char *value,
|
||||
static int set_config_idmaps(const char *key, const char *value,
|
||||
struct lxc_conf *lxc_conf, void *data)
|
||||
{
|
||||
__do_free struct lxc_list *idmaplist = NULL;
|
||||
__do_free struct id_map *idmap = NULL;
|
||||
unsigned long hostid, nsid, range;
|
||||
char type;
|
||||
@ -2219,10 +2218,6 @@ static int set_config_idmaps(const char *key, const char *value,
|
||||
if (lxc_config_value_empty(value))
|
||||
return lxc_clear_idmaps(lxc_conf);
|
||||
|
||||
idmaplist = lxc_list_new();
|
||||
if (!idmaplist)
|
||||
return ret_errno(ENOMEM);
|
||||
|
||||
idmap = zalloc(sizeof(*idmap));
|
||||
if (!idmap)
|
||||
return ret_errno(ENOMEM);
|
||||
@ -2242,8 +2237,7 @@ static int set_config_idmaps(const char *key, const char *value,
|
||||
idmap->hostid = hostid;
|
||||
idmap->nsid = nsid;
|
||||
idmap->range = range;
|
||||
idmaplist->elem = idmap;
|
||||
lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
|
||||
list_add_tail(&idmap->head, &lxc_conf->id_map);
|
||||
|
||||
if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_UID)
|
||||
if (idmap->nsid == 0)
|
||||
@ -2254,7 +2248,6 @@ static int set_config_idmaps(const char *key, const char *value,
|
||||
lxc_conf->root_nsgid_map = idmap;
|
||||
|
||||
move_ptr(idmap);
|
||||
move_ptr(idmaplist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3996,7 +3989,7 @@ static inline int get_config_cgroup_relative(const char *key, char *retv,
|
||||
static int get_config_idmaps(const char *key, char *retv, int inlen,
|
||||
struct lxc_conf *c, void *data)
|
||||
{
|
||||
struct lxc_list *it;
|
||||
struct id_map *map;
|
||||
int len, listlen, ret;
|
||||
int fulllen = 0;
|
||||
/* "u 1000 1000000 65536"
|
||||
@ -4027,9 +4020,8 @@ static int get_config_idmaps(const char *key, char *retv, int inlen,
|
||||
else
|
||||
memset(retv, 0, inlen);
|
||||
|
||||
listlen = lxc_list_len(&c->id_map);
|
||||
lxc_list_for_each(it, &c->id_map) {
|
||||
struct id_map *map = it->elem;
|
||||
listlen = list_len(&c->id_map);
|
||||
list_for_each_entry(map, &c->id_map, head) {
|
||||
ret = strnprintf(buf, sizeof(buf), "%c %lu %lu %lu",
|
||||
(map->idtype == ID_TYPE_UID) ? 'u' : 'g',
|
||||
map->nsid, map->hostid, map->range);
|
||||
|
@ -668,7 +668,7 @@ static void must_append_sized(char **buf, size_t *bufsz, const char *data, size_
|
||||
|
||||
static bool is_privileged(struct lxc_conf *conf)
|
||||
{
|
||||
return lxc_list_empty(&conf->id_map);
|
||||
return list_empty(&conf->id_map);
|
||||
}
|
||||
|
||||
static const char* AA_ALL_DEST_PATH_LIST[] = {
|
||||
|
@ -1219,7 +1219,7 @@ static int do_create_container_dir(const char *path, struct lxc_conf *conf)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (!lxc_list_empty(&conf->id_map)) {
|
||||
if (!list_empty(&conf->id_map)) {
|
||||
ret = chown_mapped_root(path, conf);
|
||||
if (ret < 0)
|
||||
ret = -1;
|
||||
@ -1290,7 +1290,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
|
||||
/* If we are not root, chown the rootfs dir to root in the target user
|
||||
* namespace.
|
||||
*/
|
||||
if (am_guest_unpriv() || !lxc_list_empty(&c->lxc_conf->id_map)) {
|
||||
if (am_guest_unpriv() || !list_empty(&c->lxc_conf->id_map)) {
|
||||
ret = chown_mapped_root(bdev->dest, c->lxc_conf);
|
||||
if (ret < 0) {
|
||||
ERROR("Error chowning \"%s\" to container root", bdev->dest);
|
||||
@ -1482,11 +1482,10 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
|
||||
* ... <-m mapn> -- and we append "--mapped-uid x", where x is
|
||||
* the mapped uid for our geteuid()
|
||||
*/
|
||||
if (!lxc_list_empty(&conf->id_map)) {
|
||||
if (!list_empty(&conf->id_map)) {
|
||||
int extraargs, hostuid_mapped, hostgid_mapped;
|
||||
char **n2;
|
||||
char txtuid[20], txtgid[20];
|
||||
struct lxc_list *it;
|
||||
struct id_map *map;
|
||||
int n2args = 1;
|
||||
|
||||
@ -1498,8 +1497,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
|
||||
tpath = "lxc-usernsexec";
|
||||
n2[0] = "lxc-usernsexec";
|
||||
|
||||
lxc_list_for_each(it, &conf->id_map) {
|
||||
map = it->elem;
|
||||
list_for_each_entry(map, &conf->id_map, head) {
|
||||
n2args += 2;
|
||||
n2 = realloc(n2, n2args * sizeof(char *));
|
||||
if (!n2)
|
||||
@ -2239,7 +2237,7 @@ static inline bool enter_net_ns(struct lxc_container *c)
|
||||
if (pid < 0)
|
||||
return false;
|
||||
|
||||
if ((geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) &&
|
||||
if ((geteuid() != 0 || (c->lxc_conf && !list_empty(&c->lxc_conf->id_map))) &&
|
||||
(access("/proc/self/ns/user", F_OK) == 0))
|
||||
if (!switch_to_ns(pid, "user"))
|
||||
return false;
|
||||
@ -5077,7 +5075,7 @@ static int do_lxcapi_mount(struct lxc_container *c, const char *source,
|
||||
}
|
||||
|
||||
/* Enter the container namespaces */
|
||||
if (!lxc_list_empty(&c->lxc_conf->id_map)) {
|
||||
if (!list_empty(&c->lxc_conf->id_map)) {
|
||||
if (!switch_to_ns(init_pid, "user")) {
|
||||
ERROR("Failed to enter user namespace");
|
||||
_exit(EXIT_FAILURE);
|
||||
@ -5170,7 +5168,7 @@ static int do_lxcapi_umount(struct lxc_container *c, const char *target,
|
||||
}
|
||||
|
||||
/* Enter the container namespaces */
|
||||
if (!lxc_list_empty(&c->lxc_conf->id_map)) {
|
||||
if (!list_empty(&c->lxc_conf->id_map)) {
|
||||
if (!switch_to_ns(init_pid, "user")) {
|
||||
ERROR("Failed to enter user namespace");
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -1110,7 +1110,7 @@ static int do_start(void *data)
|
||||
/* If we are in a new user namespace, become root there to have
|
||||
* privilege over our namespace.
|
||||
*/
|
||||
if (!lxc_list_empty(&handler->conf->id_map)) {
|
||||
if (!list_empty(&handler->conf->id_map)) {
|
||||
if (!handler->conf->root_nsuid_map)
|
||||
nsuid = handler->conf->init_uid;
|
||||
|
||||
@ -1406,7 +1406,7 @@ static int do_start(void *data)
|
||||
* we switched to root in the new user namespace further above. Only
|
||||
* drop groups if we can, so ensure that we have necessary privilege.
|
||||
*/
|
||||
if (lxc_list_empty(&handler->conf->id_map)) {
|
||||
if (list_empty(&handler->conf->id_map)) {
|
||||
#if HAVE_LIBCAP
|
||||
if (lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE))
|
||||
#endif
|
||||
@ -1473,7 +1473,7 @@ int resolve_clone_flags(struct lxc_handler *handler)
|
||||
if ((conf->ns_clone & ns_info[i].clone_flag))
|
||||
handler->ns_clone_flags |= ns_info[i].clone_flag;
|
||||
} else {
|
||||
if (i == LXC_NS_USER && lxc_list_empty(&handler->conf->id_map))
|
||||
if (i == LXC_NS_USER && list_empty(&handler->conf->id_map))
|
||||
continue;
|
||||
|
||||
if (i == LXC_NS_NET && lxc_requests_empty_network(handler))
|
||||
@ -1576,7 +1576,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
int i, ret;
|
||||
char pidstr[20];
|
||||
bool wants_to_map_ids;
|
||||
struct lxc_list *id_map;
|
||||
struct list_head *id_map;
|
||||
const char *name = handler->name;
|
||||
const char *lxcpath = handler->lxcpath;
|
||||
bool share_ns = false;
|
||||
@ -1584,7 +1584,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
|
||||
|
||||
id_map = &conf->id_map;
|
||||
wants_to_map_ids = !lxc_list_empty(id_map);
|
||||
wants_to_map_ids = !list_empty(id_map);
|
||||
|
||||
for (i = 0; i < LXC_NS_MAX; i++) {
|
||||
if (!conf->ns_share[i])
|
||||
@ -2012,14 +2012,14 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
|
||||
* it readonly.
|
||||
* If the container is unprivileged then skip rootfs pinning.
|
||||
*/
|
||||
ret = lxc_rootfs_init(conf, !lxc_list_empty(&conf->id_map));
|
||||
ret = lxc_rootfs_init(conf, !list_empty(&conf->id_map));
|
||||
if (ret) {
|
||||
ERROR("Failed to handle rootfs pinning for container \"%s\"", handler->name);
|
||||
ret = -1;
|
||||
goto out_abort;
|
||||
}
|
||||
|
||||
if (geteuid() == 0 && !lxc_list_empty(&conf->id_map)) {
|
||||
if (geteuid() == 0 && !list_empty(&conf->id_map)) {
|
||||
/*
|
||||
* Most filesystems can't be mounted inside a userns so handle them here.
|
||||
*/
|
||||
|
@ -57,7 +57,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
|
||||
if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
|
||||
ret = chown_mapped_root(new->dest, conf);
|
||||
if (ret < 0)
|
||||
WARN("Failed to update ownership of %s", new->dest);
|
||||
@ -88,7 +88,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
|
||||
if (ret < 0 && errno != EEXIST)
|
||||
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work);
|
||||
|
||||
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
|
||||
if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
|
||||
__do_free char *lxc_overlay_delta_dir = NULL,
|
||||
*lxc_overlay_private_dir = NULL;
|
||||
|
||||
@ -155,7 +155,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
|
||||
if (ret < 0 && errno != EEXIST)
|
||||
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
|
||||
|
||||
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
|
||||
if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
|
||||
__do_free char *lxc_overlay_delta_dir = NULL,
|
||||
*lxc_overlay_private_dir = NULL;
|
||||
|
||||
@ -276,7 +276,7 @@ int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
|
||||
if (ret < 0 && errno != EEXIST)
|
||||
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
|
||||
|
||||
if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
|
||||
if (am_guest_unpriv() || !list_empty(&conf->id_map)) {
|
||||
__do_free char *lxc_overlay_private_dir = NULL;
|
||||
|
||||
lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL);
|
||||
|
@ -876,7 +876,7 @@ static int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *termina
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (lxc_list_empty(&c->id_map))
|
||||
if (list_empty(&c->id_map))
|
||||
return 0;
|
||||
|
||||
if (is_empty_string(terminal->name) && terminal->pty < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user