[lxc-devel] [lxc/master] conf: add userns_exec_full()
brauner on Github
lxc-bot at linuxcontainers.org
Sat Sep 9 09:25:31 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 381 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170909/c21459bb/attachment.bin>
-------------- next part --------------
From 415a8851483d354f8e95d6d9788687fbdf48a69d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
Date: Sat, 9 Sep 2017 11:21:51 +0200
Subject: [PATCH 3/7] start: userns_exec_full()
Closes #1800.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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");
More information about the lxc-devel
mailing list