The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1801
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Closes #1800. Signed-off-by: Christian Brauner <[email protected]>
From 415a8851483d354f8e95d6d9788687fbdf48a69d Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:20:57 +0200 Subject: [PATCH 1/7] conf: add userns_exec_full() Closes #1800. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/conf.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/lxc/conf.h | 2 + 2 files changed, 181 insertions(+), 2 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 7a1188165..8544e32f5 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3816,8 +3816,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, ret = lxc_map_ids(idmap, pid); if (ret < 0) { ERROR("error setting up {g,u}id mappings for child process " - "\"%d\"", - pid); + "\"%d\"", pid); goto on_error; } @@ -3849,6 +3848,184 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, return ret; } +int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, + const char *fn_name) +{ + pid_t pid; + uid_t euid, egid; + struct userns_fn_data d; + int p[2]; + struct id_map *map; + struct lxc_list *cur; + char c = '1'; + int ret = -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; + + ret = pipe(p); + if (ret < 0) { + SYSERROR("opening pipe"); + return -1; + } + d.fn = fn; + d.fn_name = fn_name; + d.arg = data; + d.p[0] = p[0]; + d.p[1] = p[1]; + + /* Clone child in new user namespace. */ + pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER); + if (pid < 0) { + ERROR("failed to clone child process in new user namespace"); + goto on_error; + } + + close(p[0]); + p[0] = -1; + + euid = geteuid(); + egid = getegid(); + + /* Allocate new {g,u}id map list. */ + idmap = malloc(sizeof(*idmap)); + if (!idmap) + goto on_error; + lxc_list_init(idmap); + + /* Find container root. */ + lxc_list_for_each(cur, &conf->id_map) { + struct id_map *tmpmap; + + tmplist = malloc(sizeof(*tmplist)); + if (!tmplist) + goto on_error; + + tmpmap = malloc(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; + + if (map->idtype == ID_TYPE_UID) + if (euid >= map->hostid && euid < map->hostid + map->range) + host_uid_map = map; + + if (map->idtype == ID_TYPE_GID) + if (egid >= map->hostid && egid < map->hostid + map->range) + host_gid_map = map; + + if (map->nsid != 0) + continue; + + if (map->idtype == ID_TYPE_UID) + if (container_root_uid == NULL) + container_root_uid = map; + + if (map->idtype == ID_TYPE_GID) + if (container_root_gid == NULL) + container_root_gid = map; + } + + if (!container_root_uid || !container_root_gid) { + ERROR("No mapping for container root found"); + goto on_error; + } + + /* Check whether the {g,u}id of the user has a mapping. */ + if (!host_uid_map) + host_uid_map = idmap_add(conf, euid, ID_TYPE_UID); + else + host_uid_map = container_root_uid; + + if (!host_gid_map) + host_gid_map = idmap_add(conf, egid, ID_TYPE_GID); + else + host_gid_map = container_root_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; + } + + if (host_uid_map && (host_uid_map != container_root_uid)) { + /* 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; + + if (host_gid_map && (host_gid_map != container_root_gid)) { + 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_LEVEL_TRACE || + conf->loglevel == LXC_LOG_LEVEL_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", + (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); + if (ret < 0) { + ERROR("error setting up {g,u}id mappings for child process " + "\"%d\"", pid); + goto on_error; + } + + /* Tell child to proceed. */ + if (write(p[1], &c, 1) != 1) { + SYSERROR("failed telling child process \"%d\" to proceed", pid); + goto on_error; + } + + /* Wait for child to finish. */ + ret = wait_for_pid(pid); + +on_error: + if (idmap) + lxc_free_idmap(idmap); + if (host_uid_map && (host_uid_map != container_root_uid)) + free(host_uid_map); + if (host_gid_map && (host_gid_map != container_root_gid)) + free(host_gid_map); + + if (p[0] != -1) + close(p[0]); + close(p[1]); + + return ret; +} + /* not thread-safe, do not use from api without first forking */ static char* getuname(void) { diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 882c9cd83..946ae4a23 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -381,6 +381,8 @@ extern int chown_mapped_root(char *path, struct lxc_conf *conf); extern int lxc_ttys_shift_ids(struct lxc_conf *c); extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, const char *fn_name); +extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), + void *data, const char *fn_name); extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata); extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); From ee484f7f6851088b16532ea82bce506b1434c05a Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:21:16 +0200 Subject: [PATCH 2/7] lxccontainer: use userns_exec_full() Closes #1800. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/lxccontainer.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 093a2992b..5e8ad00f9 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -2569,12 +2569,17 @@ static bool has_snapshots(struct lxc_container *c) } static bool do_destroy_container(struct lxc_conf *conf) { + int ret; + if (am_unpriv()) { - if (userns_exec_1(conf, storage_destroy_wrapper, conf, - "storage_destroy_wrapper") < 0) + ret = userns_exec_full(conf, storage_destroy_wrapper, conf, + "storage_destroy_wrapper"); + if (ret < 0) return false; + return true; } + return storage_destroy(conf); } @@ -2708,8 +2713,8 @@ static bool container_destroy(struct lxc_container *c, if (ret < 0 || (size_t)ret >= len) goto out; if (am_unpriv()) - ret = userns_exec_1(conf, lxc_rmdir_onedev_wrapper, path, - "lxc_rmdir_onedev_wrapper"); + ret = userns_exec_full(conf, lxc_rmdir_onedev_wrapper, path, + "lxc_rmdir_onedev_wrapper"); else ret = lxc_rmdir_onedev(path, "snaps"); if (ret < 0) { @@ -3551,8 +3556,8 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char data.flags = flags; data.hookargs = hookargs; if (am_unpriv()) - ret = userns_exec_1(c->lxc_conf, clone_update_rootfs_wrapper, - &data, "clone_update_rootfs_wrapper"); + ret = userns_exec_full(c->lxc_conf, clone_update_rootfs_wrapper, + &data, "clone_update_rootfs_wrapper"); else ret = clone_update_rootfs(&data); if (ret < 0) From 94b0a3ac393d0081520a0f32004ce15e2ade13af Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:21:51 +0200 Subject: [PATCH 3/7] start: userns_exec_full() Closes #1800. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/start.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index 1370d681c..4fc289557 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1596,8 +1596,8 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler, } if (!handler->am_root) - ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, - destroy, "lxc_rmdir_onedev_wrapper"); + ret = userns_exec_full(handler->conf, lxc_rmdir_onedev_wrapper, + destroy, "lxc_rmdir_onedev_wrapper"); else ret = lxc_rmdir_onedev(destroy, NULL); @@ -1615,9 +1615,12 @@ static int lxc_rmdir_onedev_wrapper(void *data) } static bool do_destroy_container(struct lxc_handler *handler) { + int ret; + if (!handler->am_root) { - if (userns_exec_1(handler->conf, storage_destroy_wrapper, - handler->conf, "storage_destroy_wrapper") < 0) + ret = userns_exec_full(handler->conf, storage_destroy_wrapper, + handler->conf, "storage_destroy_wrapper"); + if (ret < 0) return false; return true; From 5c05427a60171963fa56d45150374080fe2f223f Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:22:44 +0200 Subject: [PATCH 4/7] storage: use userns_exec_full() Closes #1800. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/storage/aufs.c | 4 ++-- src/lxc/storage/btrfs.c | 4 ++-- src/lxc/storage/overlay.c | 4 ++-- src/lxc/storage/storage.c | 5 +++-- src/lxc/storage/storage.h | 1 - 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lxc/storage/aufs.c b/src/lxc/storage/aufs.c index 312c32bcd..a39cd60aa 100644 --- a/src/lxc/storage/aufs.c +++ b/src/lxc/storage/aufs.c @@ -164,8 +164,8 @@ int aufs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, rdata.src = odelta; rdata.dest = ndelta; if (am_unpriv()) - ret = userns_exec_1(conf, lxc_rsync_delta_wrapper, - &rdata, "lxc_rsync_delta_wrapper"); + ret = userns_exec_full(conf, lxc_rsync_delta_wrapper, + &rdata, "lxc_rsync_delta_wrapper"); else ret = run_command(cmd_output, sizeof(cmd_output), lxc_rsync_delta_wrapper, diff --git a/src/lxc/storage/btrfs.c b/src/lxc/storage/btrfs.c index 1fe0d5acd..29b44dfdf 100644 --- a/src/lxc/storage/btrfs.c +++ b/src/lxc/storage/btrfs.c @@ -434,8 +434,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, data.orig = orig; data.new = new; if (am_unpriv()) { - ret = userns_exec_1(conf, lxc_storage_rsync_exec_wrapper, &data, - "lxc_storage_rsync_exec_wrapper"); + ret = userns_exec_full(conf, lxc_storage_rsync_exec_wrapper, + &data, "lxc_storage_rsync_exec_wrapper"); if (ret < 0) { ERROR("Failed to rsync from \"%s\" into \"%s\"", orig->dest, new->dest); diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c index e63a6ba56..7fe4536bb 100644 --- a/src/lxc/storage/overlay.c +++ b/src/lxc/storage/overlay.c @@ -971,8 +971,8 @@ static int ovl_do_rsync(const char *src, const char *dest, rdata.src = (char *)src; rdata.dest = (char *)dest; if (am_unpriv()) - ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata, - "lxc_rsync_exec_wrapper"); + ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata, + "lxc_rsync_exec_wrapper"); else ret = run_command(cmd_output, sizeof(cmd_output), lxc_rsync_exec_wrapper, (void *)&rdata); diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c index fee3d8df1..30aaaaa93 100644 --- a/src/lxc/storage/storage.c +++ b/src/lxc/storage/storage.c @@ -502,8 +502,9 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname, data.orig = orig; data.new = new; if (am_unpriv()) - ret = userns_exec_1(c->lxc_conf, lxc_storage_rsync_exec_wrapper, - &data, "lxc_storage_rsync_exec_wrapper"); + ret = userns_exec_full(c->lxc_conf, + lxc_storage_rsync_exec_wrapper, &data, + "lxc_storage_rsync_exec_wrapper"); else ret = run_command(cmd_output, sizeof(cmd_output), lxc_storage_rsync_exec_wrapper, (void *)&data); diff --git a/src/lxc/storage/storage.h b/src/lxc/storage/storage.h index aa819df65..c656d3952 100644 --- a/src/lxc/storage/storage.h +++ b/src/lxc/storage/storage.h @@ -136,7 +136,6 @@ extern struct lxc_storage *storage_create(const char *dest, const char *type, extern void storage_put(struct lxc_storage *bdev); extern bool storage_destroy(struct lxc_conf *conf); -/* callback function to be used with userns_exec_1() */ extern int storage_destroy_wrapper(void *data); extern bool rootfs_is_blockdev(struct lxc_conf *conf); extern char *lxc_storage_get_path(char *src, const char *prefix); From a05a723f6a08fecfbef68a02dc0080c2ca9ac9ad Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:23:14 +0200 Subject: [PATCH 5/7] console: remove dead assignments non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/console.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lxc/console.c b/src/lxc/console.c index 97ae7a16e..c882b85c6 100644 --- a/src/lxc/console.c +++ b/src/lxc/console.c @@ -480,7 +480,6 @@ static int lxc_console_peer_default(struct lxc_console *console) console->tios = malloc(sizeof(*console->tios)); if (!console->tios) { SYSERROR("failed to allocate memory"); - ret = -ENOMEM; goto on_error1; } @@ -492,7 +491,6 @@ static int lxc_console_peer_default(struct lxc_console *console) on_error2: free(console->tios); console->tios = NULL; - ret = -ENOTTY; on_error1: close(console->peer); From 4dd08ac85fe302c288284d4dabb76462d67c2877 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:23:34 +0200 Subject: [PATCH 6/7] monitor: remove dead assignment non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/monitor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c index 63a404d62..166329a7c 100644 --- a/src/lxc/monitor.c +++ b/src/lxc/monitor.c @@ -243,7 +243,6 @@ int lxc_monitor_open(const char *lxcpath) ERROR("Failed to connect to monitor socket: %s.", strerror(errno)); goto on_error; } - ret = 0; return fd; From 9e2bdae4a64ccbf59d9e402951be2ca01ecb5449 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Sat, 9 Sep 2017 11:23:55 +0200 Subject: [PATCH 7/7] start: remove dead variable non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/start.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index 4fc289557..3ccb73311 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1142,7 +1142,7 @@ static int lxc_spawn(struct lxc_handler *handler) bool wants_to_map_ids; int saved_ns_fd[LXC_NS_MAX]; struct lxc_list *id_map; - int failed_before_rename = 0, preserve_mask = 0; + int preserve_mask = 0; bool cgroups_connected = false; id_map = &handler->conf->id_map; @@ -1256,15 +1256,11 @@ static int lxc_spawn(struct lxc_handler *handler) goto out_delete_net; } - if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) { - failed_before_rename = 1; + if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) goto out_delete_net; - } - if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) { - failed_before_rename = 1; + if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) goto out_delete_net; - } if (!cgroup_create_legacy(handler)) { ERROR("Failed to setup legacy cgroups for container \"%s\".", name); @@ -1281,9 +1277,6 @@ static int lxc_spawn(struct lxc_handler *handler) if (!cgroup_chown(handler)) goto out_delete_net; - if (failed_before_rename) - goto out_delete_net; - handler->netnsfd = lxc_preserve_ns(handler->pid, "net"); if (handler->netnsfd < 0) { ERROR("Failed to preserve network namespace");
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
