[lxc-devel] [lxc/master] confile: add lxc.namespace.<namespace-key>

brauner on Github lxc-bot at linuxcontainers.org
Sun Oct 29 11:33:45 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 385 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171029/a171322c/attachment.bin>
-------------- next part --------------
From 1f07ab493f25630d2fb9278ef4b10d7e1d5e79e4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 28 Oct 2017 15:30:04 +0200
Subject: [PATCH 1/3] lxc-start: remove unnecessary checks

The console struct is internal and liblxc takes care of creating paths.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/tools/lxc_start.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 639248e0e..69e00471e 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -326,16 +326,6 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	if (ensure_path(&conf->console.path, my_args.console) < 0) {
-		ERROR("failed to ensure console path '%s'", my_args.console);
-		goto out;
-	}
-
-	if (ensure_path(&conf->console.log_path, my_args.console_log) < 0) {
-		ERROR("failed to ensure console log '%s'", my_args.console_log);
-		goto out;
-	}
-
 	if (my_args.pidfile != NULL) {
 		if (ensure_path(&c->pidfile, my_args.pidfile) < 0) {
 			ERROR("failed to ensure pidfile '%s'", my_args.pidfile);

From 01410bfa38ae531b4a00dd8ed23142f7d14d429d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 28 Oct 2017 22:05:18 +0200
Subject: [PATCH 2/3] handler: make name argument const

There's no obvious need to strdup() the name of the container in the handler.
We can simply make this a pointer to the memory allocated in
lxc_container_new().

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c |  2 +-
 src/lxc/network.c  |  8 ++++----
 src/lxc/network.h  |  4 ++--
 src/lxc/start.c    | 10 +---------
 src/lxc/start.h    |  6 +++---
 5 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 4d440ba78..86d5b0208 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -835,7 +835,7 @@ static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
 
 	memset(&rsp, 0, sizeof(rsp));
 
-	rsp.data = handler->name;
+	rsp.data = (char *)handler->name;
 	rsp.datalen = strlen(handler->name) + 1;
 	rsp.ret = 0;
 
diff --git a/src/lxc/network.c b/src/lxc/network.c
index 909b7e58b..da6259447 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -2050,7 +2050,7 @@ int lxc_find_gateway_addresses(struct lxc_handler *handler)
 }
 
 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
-static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
+static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname,
 					  struct lxc_netdev *netdev, pid_t pid)
 {
 	int ret;
@@ -2194,7 +2194,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
 	return 0;
 }
 
-static int lxc_delete_network_unpriv_exec(const char *lxcpath, char *lxcname,
+static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcname,
 					  struct lxc_netdev *netdev,
 					  const char *netns_path)
 {
@@ -2408,7 +2408,7 @@ int lxc_create_network_priv(struct lxc_handler *handler)
 	return 0;
 }
 
-int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname,
+int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcname,
 					 struct lxc_list *network, pid_t pid)
 {
 	int ret;
@@ -2448,7 +2448,7 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname,
 	return 0;
 }
 
-int lxc_create_network_unpriv(const char *lxcpath, char *lxcname,
+int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
 			      struct lxc_list *network, pid_t pid)
 {
 	struct lxc_list *iterator;
diff --git a/src/lxc/network.h b/src/lxc/network.h
index 3bacdc2b0..971ef367d 100644
--- a/src/lxc/network.h
+++ b/src/lxc/network.h
@@ -263,12 +263,12 @@ extern int setup_private_host_hw_addr(char *veth1);
 extern int netdev_get_mtu(int ifindex);
 extern int lxc_create_network_priv(struct lxc_handler *handler);
 extern int lxc_network_move_created_netdev_priv(const char *lxcpath,
-						char *lxcname,
+						const char *lxcname,
 						struct lxc_list *network,
 						pid_t pid);
 extern void lxc_delete_network(struct lxc_handler *handler);
 extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
-extern int lxc_create_network_unpriv(const char *lxcpath, char *lxcname,
+extern int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
 				     struct lxc_list *network, pid_t pid);
 extern int lxc_requests_empty_network(struct lxc_handler *handler);
 extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 7748dbf61..fd3136f8c 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -525,9 +525,6 @@ void lxc_free_handler(struct lxc_handler *handler)
 	if (handler->state_socket_pair[1] >= 0)
 		close(handler->state_socket_pair[1]);
 
-	if (handler->name)
-		free(handler->name);
-
 	handler->conf = NULL;
 	free(handler);
 }
@@ -561,11 +558,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
 	for (i = 0; i < LXC_NS_MAX; i++)
 		handler->nsfd[i] = -1;
 
-	handler->name = strdup(name);
-	if (!handler->name) {
-		ERROR("failed to allocate memory");
-		goto on_error;
-	}
+	handler->name = name;
 
 	if (daemonize && !handler->conf->reboot) {
 		/* Create socketpair() to synchronize on daemonized startup.
@@ -786,7 +779,6 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1)
 		lxc_destroy_container_on_signal(handler, name);
 
-	free(handler->name);
 	free(handler);
 }
 
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 5955dfd79..be724bcaf 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -67,10 +67,10 @@ struct lxc_handler {
 	/* Socketpair to synchronize processes during container creation. */
 	int sync_sock[2];
 
-	/* The name of the container. */
-	char *name;
+	/* Pointer to the name of the container. Do not free! */
+	const char *name;
 
-	/* The path the container is running in. */
+	/* Pointer to the path the container. Do not free! */
 	const char *lxcpath;
 
 	/* Whether the container's startup process euid is 0. */

From 8e30b6d0a7852d529e92d5deb987d3412d19bb2c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 28 Oct 2017 22:07:27 +0200
Subject: [PATCH 3/3] confile: add lxc.namespace.<namespace-key>

Relates to #1881.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c            | 17 ++++++++---
 src/lxc/conf.h            |  9 ++++--
 src/lxc/confile.c         | 62 +++++++++++++++++++++++++++++++++++++
 src/lxc/confile_utils.c   | 78 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/lxc/confile_utils.h   |  2 ++
 src/lxc/namespace.c       | 17 +++++++++--
 src/lxc/namespace.h       |  3 +-
 src/lxc/start.c           | 52 ++++++++++++++++++++++++-------
 src/lxc/tools/lxc_start.c |  2 +-
 9 files changed, 218 insertions(+), 24 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index d2fab9450..d473eca40 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2458,22 +2458,24 @@ struct lxc_conf *lxc_conf_init(void)
 	lxc_list_init(&new->aliens);
 	lxc_list_init(&new->environment);
 	lxc_list_init(&new->limits);
-	for (i=0; i<NUM_LXC_HOOKS; i++)
+	for (i = 0; i < NUM_LXC_HOOKS; i++)
 		lxc_list_init(&new->hooks[i]);
 	lxc_list_init(&new->groups);
 	new->lsm_aa_profile = NULL;
 	new->lsm_se_context = NULL;
 	new->tmp_umount_proc = 0;
 
-	for (i = 0; i < LXC_NS_MAX; i++)
-		new->inherit_ns_fd[i] = -1;
-
 	/* if running in a new user namespace, init and COMMAND
 	 * default to running as UID/GID 0 when using lxc-execute */
 	new->init_uid = 0;
 	new->init_gid = 0;
 	memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
 
+	for (i = 0; i < LXC_NS_MAX; i++) {
+		new->inherit_ns[i].value = NULL;
+		new->inherit_ns[i].fd = -1;
+	}
+
 	return new;
 }
 
@@ -3152,7 +3154,7 @@ int lxc_setup_child(struct lxc_handler *handler)
 		return -1;
 	}
 
-	if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
+	if (lxc_conf->inherit_ns[LXC_NS_UTS].fd == -1) {
 		if (setup_utsname(lxc_conf->utsname)) {
 			ERROR("failed to setup the utsname for '%s'", name);
 			return -1;
@@ -3514,6 +3516,8 @@ void lxc_clear_includes(struct lxc_conf *conf)
 
 void lxc_conf_free(struct lxc_conf *conf)
 {
+	int i;
+
 	if (!conf)
 		return;
 	if (current_config == conf)
@@ -3555,6 +3559,9 @@ void lxc_conf_free(struct lxc_conf *conf)
 	lxc_clear_limits(conf, "lxc.prlimit");
 	free(conf->cgroup_meta.dir);
 	free(conf->cgroup_meta.controllers);
+	for (i = 0; i < LXC_NS_MAX; i++)
+		if (conf->inherit_ns[i].value)
+			free(conf->inherit_ns[i].value);
 	free(conf);
 }
 
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index c61f861ed..1d5a2935a 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -237,6 +237,11 @@ enum lxchooks {
 
 extern char *lxchook_names[NUM_LXC_HOOKS];
 
+struct lxc_inherit_ns {
+	char *value;
+	int fd;
+};
+
 struct lxc_conf {
 	int is_execute;
 	char *fstab;
@@ -285,8 +290,6 @@ struct lxc_conf {
 	int loglevel; /* loglevel as specifed in config (if any) */
 	int logfd;
 
-	int inherit_ns_fd[LXC_NS_MAX];
-
 	unsigned int start_auto;
 	unsigned int start_delay;
 	int start_order;
@@ -348,6 +351,8 @@ struct lxc_conf {
 	 * that union.
 	 */
 	struct lxc_cgroup cgroup_meta;
+
+	struct lxc_inherit_ns inherit_ns[LXC_NS_MAX];
 };
 
 #ifdef HAVE_TLS
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index d94a30719..668bb82f6 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -102,6 +102,7 @@ lxc_config_define(monitor);
 lxc_config_define(mount);
 lxc_config_define(mount_auto);
 lxc_config_define(mount_fstab);
+lxc_config_define(namespace);
 lxc_config_define(net);
 lxc_config_define(net_flags);
 lxc_config_define(net_hwaddr);
@@ -178,6 +179,7 @@ static struct lxc_config_t config[] = {
 	{ "lxc.mount.auto",                false,                  set_config_mount_auto,                  get_config_mount_auto,                  clr_config_mount_auto,                },
 	{ "lxc.mount.entry",               false,                  set_config_mount,                       get_config_mount,                       clr_config_mount,                     },
 	{ "lxc.mount.fstab",               false,                  set_config_mount_fstab,                 get_config_mount_fstab,                 clr_config_mount_fstab,               },
+	{ "lxc.namespace",                 false,                  set_config_namespace,                   get_config_namespace,                   clr_config_namespace,                 },
 
 	/* [START]: REMOVE IN LXC 3.0 */
 	{ "lxc.network.type",              true,                   set_config_network_legacy_type,         get_config_network_legacy_item,         clr_config_network_legacy_item,       },
@@ -1976,6 +1978,23 @@ static int set_config_uts_name(const char *key, const char *value,
 	return 0;
 }
 
+static int set_config_namespace(const char *key, const char *value,
+				struct lxc_conf *lxc_conf, void *data)
+{
+	int ns_idx;
+	const char *namespace;
+
+	if (lxc_config_value_empty(value))
+		return clr_config_namespace(key, lxc_conf, data);
+
+	namespace = key + sizeof("lxc.namespace.") - 1;
+	ns_idx = lxc_namespace_2_ns_idx(namespace);
+	if (ns_idx < 0)
+		return ns_idx;
+
+	return set_config_string_item(&lxc_conf->inherit_ns[ns_idx].value, value);
+}
+
 struct parse_line_conf {
 	struct lxc_conf *conf;
 	bool from_include;
@@ -3268,6 +3287,28 @@ static int get_config_noop(const char *key, char *retv, int inlen,
 	return 0;
 }
 
+static int get_config_namespace(const char *key, char *retv, int inlen,
+				struct lxc_conf *c, void *data)
+{
+	int len, ns_idx;
+	const char *namespace;
+	int fulllen = 0;
+
+	if (!retv)
+		inlen = 0;
+	else
+		memset(retv, 0, inlen);
+
+	namespace = key + sizeof("lxc.namespace.") - 1;
+	ns_idx = lxc_namespace_2_ns_idx(namespace);
+	if (ns_idx < 0)
+		return ns_idx;
+
+	strprint(retv, inlen, "%s", c->inherit_ns[ns_idx].value);
+
+	return fulllen;
+}
+
 /* Callbacks to clear config items. */
 static inline int clr_config_personality(const char *key, struct lxc_conf *c,
 					 void *data)
@@ -3606,6 +3647,27 @@ static inline int clr_config_noop(const char *key, struct lxc_conf *c,
 	return 0;
 }
 
+static int clr_config_namespace(const char *key, struct lxc_conf *lxc_conf,
+				void *data)
+{
+	int ns_idx;
+	const char *namespace;
+
+	namespace = key + sizeof("lxc.namespace.") - 1;
+	ns_idx = lxc_namespace_2_ns_idx(namespace);
+	if (ns_idx < 0)
+		return ns_idx;
+
+	free(lxc_conf->inherit_ns[ns_idx].value);
+	if (lxc_conf->inherit_ns[ns_idx].fd < 0)
+		return 0;
+
+	close(lxc_conf->inherit_ns[ns_idx].fd);
+	lxc_conf->inherit_ns[ns_idx].fd = -1;
+
+	return 0;
+}
+
 static int get_config_includefiles(const char *key, char *retv, int inlen,
 				   struct lxc_conf *c, void *data)
 {
diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c
index 9db4bc6d3..1d24f28d6 100644
--- a/src/lxc/confile_utils.c
+++ b/src/lxc/confile_utils.c
@@ -29,8 +29,9 @@
 #include "confile.h"
 #include "confile_utils.h"
 #include "error.h"
-#include "log.h"
 #include "list.h"
+#include "log.h"
+#include "lxccontainer.h"
 #include "network.h"
 #include "parse.h"
 #include "utils.h"
@@ -700,3 +701,78 @@ bool parse_limit_value(const char **value, rlim_t *res)
 
 	return true;
 }
+
+static int lxc_container_name_to_pid(const char *lxcname_or_pid,
+				     const char *lxcpath)
+{
+	int ret;
+	signed long int pid;
+	char *err = NULL;
+
+	pid = strtol(lxcname_or_pid, &err, 10);
+	if (*err != '\0' || pid < 1) {
+		struct lxc_container *c;
+
+		c = lxc_container_new(lxcname_or_pid, lxcpath);
+		if (!c) {
+			ERROR("\"%s\" is not a valid pid nor a container name",
+			      lxcname_or_pid);
+			return -1;
+		}
+
+		if (!c->may_control(c)) {
+			ERROR("Insufficient privileges to control container "
+			      "\"%s\"", c->name);
+			lxc_container_put(c);
+			return -1;
+		}
+
+		pid = c->init_pid(c);
+		if (pid < 1) {
+			ERROR("Container \"%s\" is not running", c->name);
+			lxc_container_put(c);
+			return -1;
+		}
+
+		lxc_container_put(c);
+	}
+
+	ret = kill(pid, 0);
+	if (ret < 0) {
+		ERROR("%s - Failed to send signal to pid %d", strerror(errno),
+		      (int)pid);
+		return -EPERM;
+	}
+
+	return pid;
+}
+
+int lxc_inherit_namespace(struct lxc_inherit_ns *ns, const char *lxcpath,
+			  const char *namespace)
+{
+	int fd, pid;
+	char *dup, *lastslash;
+
+	lastslash = strrchr(ns->value, '/');
+	if (lastslash) {
+		dup = strdup(ns->value);
+		if (!dup)
+			return -ENOMEM;
+
+		*lastslash = '\0';
+		pid = lxc_container_name_to_pid(lastslash, dup);
+		free(dup);
+	} else {
+		pid = lxc_container_name_to_pid(ns->value, lxcpath);
+	}
+
+	if (pid < 0)
+		return -EINVAL;
+
+	fd = lxc_preserve_ns(pid, namespace);
+	if (fd < 0)
+		return -EINVAL;
+
+	ns->fd = fd;
+	return 0;
+}
diff --git a/src/lxc/confile_utils.h b/src/lxc/confile_utils.h
index ee9376e24..90199e6ed 100644
--- a/src/lxc/confile_utils.h
+++ b/src/lxc/confile_utils.h
@@ -86,5 +86,7 @@ extern int lxc_get_conf_str(char *retv, int inlen, const char *value);
 extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v);
 extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v);
 extern bool parse_limit_value(const char **value, rlim_t *res);
+extern int lxc_inherit_namespace(struct lxc_inherit_ns *ns, const char *lxcpath,
+				 const char *namespace);
 
 #endif /* __LXC_CONFILE_UTILS_H */
diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c
index e760c0d9a..da434052a 100644
--- a/src/lxc/namespace.c
+++ b/src/lxc/namespace.c
@@ -96,15 +96,26 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
 	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
 };
 
-int lxc_namespace_2_cloneflag(char *namespace)
+int lxc_namespace_2_cloneflag(const char *namespace)
 {
 	int i;
 	for (i = 0; i < LXC_NS_MAX; i++)
 		if (!strcasecmp(ns_info[i].proc_name, namespace))
 			return ns_info[i].clone_flag;
 
-	ERROR("Invalid namespace name: %s.", namespace);
-	return -1;
+	ERROR("Invalid namespace name \"%s\"", namespace);
+	return -EINVAL;
+}
+
+int lxc_namespace_2_ns_idx(const char *namespace)
+{
+	int i;
+	for (i = 0; i < LXC_NS_MAX; i++)
+		if (!strcmp(ns_info[i].proc_name, namespace))
+			return i;
+
+	ERROR("Invalid namespace name \"%s\"", namespace);
+	return -EINVAL;
 }
 
 int lxc_fill_namespace_flags(char *flaglist, int *flags)
diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h
index 4916950c1..02ec08885 100644
--- a/src/lxc/namespace.h
+++ b/src/lxc/namespace.h
@@ -81,7 +81,8 @@ int clone(int (*fn)(void *), void *child_stack,
 
 extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
 
-extern int lxc_namespace_2_cloneflag(char *namespace);
+extern int lxc_namespace_2_cloneflag(const char *namespace);
+extern int lxc_namespace_2_ns_idx(const char *namespace);
 extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
 
 #endif
diff --git a/src/lxc/start.c b/src/lxc/start.c
index fd3136f8c..ce9e4061e 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -238,7 +238,7 @@ int lxc_check_inherited(struct lxc_conf *conf, bool closeall,
 
 		if (conf) {
 			for (i = 0; i < LXC_NS_MAX; i++)
-				if (conf->inherit_ns_fd[i] == fd)
+				if (conf->inherit_ns[i].fd == fd)
 					break;
 
 			if (i < LXC_NS_MAX)
@@ -722,11 +722,18 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 
 	while (namespace_count--)
 		free(namespaces[namespace_count]);
+
 	for (i = 0; i < LXC_NS_MAX; i++) {
 		if (handler->nsfd[i] != -1) {
 			close(handler->nsfd[i]);
 			handler->nsfd[i] = -1;
 		}
+
+		if (handler->conf->inherit_ns[i].fd < 0) {
+			close(handler->conf->inherit_ns[i].fd);
+			handler->conf->inherit_ns[i].fd = -1;
+		}
+
 	}
 
 	if (handler->netnsfd >= 0) {
@@ -1123,24 +1130,24 @@ void resolve_clone_flags(struct lxc_handler *handler)
 	if (!lxc_list_empty(&handler->conf->id_map))
 		handler->clone_flags |= CLONE_NEWUSER;
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
+	if (handler->conf->inherit_ns[LXC_NS_NET].fd == -1) {
 		if (!lxc_requests_empty_network(handler))
 			handler->clone_flags |= CLONE_NEWNET;
 	} else {
 		INFO("Inheriting a NET namespace.");
 	}
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1)
+	if (handler->conf->inherit_ns[LXC_NS_IPC].fd == -1)
 		handler->clone_flags |= CLONE_NEWIPC;
 	else
 		INFO("Inheriting an IPC namespace.");
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1)
+	if (handler->conf->inherit_ns[LXC_NS_UTS].fd == -1)
 		handler->clone_flags |= CLONE_NEWUTS;
 	else
 		INFO("Inheriting a UTS namespace.");
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_PID] == -1)
+	if (handler->conf->inherit_ns[LXC_NS_PID].fd == -1)
 		handler->clone_flags |= CLONE_NEWPID;
 	else
 		INFO("Inheriting a PID namespace.");
@@ -1156,20 +1163,34 @@ void resolve_clone_flags(struct lxc_handler *handler)
 static int lxc_spawn(struct lxc_handler *handler)
 {
 	int i, flags, ret;
-	const char *name = handler->name;
 	char pidstr[20];
 	bool wants_to_map_ids;
 	int saved_ns_fd[LXC_NS_MAX];
 	struct lxc_list *id_map;
 	int preserve_mask = 0;
+	const char *name = handler->name;
+	const char *lxcpath = handler->lxcpath;
 	bool cgroups_connected = false;
 
 	id_map = &handler->conf->id_map;
 	wants_to_map_ids = !lxc_list_empty(id_map);
 
-	for (i = 0; i < LXC_NS_MAX; i++)
-		if (handler->conf->inherit_ns_fd[i] != -1)
-			preserve_mask |= ns_info[i].clone_flag;
+	for (i = 0; i < LXC_NS_MAX; i++) {
+		struct lxc_inherit_ns *ns;
+
+		ns = &handler->conf->inherit_ns[i];
+		if (!ns->value)
+			continue;
+
+		preserve_mask |= ns_info[i].clone_flag;
+
+		if (ns->fd >= 0)
+			continue;
+
+		ret = lxc_inherit_namespace(ns, lxcpath, ns_info[i].proc_name);
+		if (ret < 0)
+			return -1;
+	}
 
 	if (lxc_sync_init(handler))
 		return -1;
@@ -1233,8 +1254,17 @@ static int lxc_spawn(struct lxc_handler *handler)
 	if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
 		goto out_delete_net;
 
-	if (attach_ns(handler->conf->inherit_ns_fd) < 0)
-		goto out_delete_net;
+	for (i = 0; i < LXC_NS_MAX; i++) {
+		const struct lxc_inherit_ns *ns;
+
+		ns = &handler->conf->inherit_ns[i];
+		if (ns->fd < 0)
+			continue;
+
+		ret = setns(ns->fd, 0);
+		if (ret < 0)
+			goto out_delete_net;
+	}
 
 	/* Create a process in a new set of namespaces. */
 	flags = handler->clone_flags;
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 69e00471e..a8b1f7043 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -345,7 +345,7 @@ int main(int argc, char *argv[])
 		int fd = open_ns(pid, ns_info[i].proc_name);
 		if (fd < 0)
 			goto out;
-		conf->inherit_ns_fd[i] = fd;
+		conf->inherit_ns[i].fd = fd;
 	}
 
 	if (!my_args.daemonize) {


More information about the lxc-devel mailing list