[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