]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
confile: add lxc.namespace.<namespace-key>
authorChristian Brauner <christian.brauner@ubuntu.com>
Sat, 28 Oct 2017 20:07:27 +0000 (22:07 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 3 Nov 2017 07:37:09 +0000 (08:37 +0100)
This commit also gets rid of ~10 unnecessarily file descriptors that were kept
open. Before we kept open:

- A set of file descriptors that refer to the monitor's namespaces. These were
  only used to reattach to the monitor's namespace in lxc_spawn() and were
  never used anywhere else. So close them and don't keep them around.
- A list of inherited file descriptors.
- A list of file descriptors referring to the containers's namespaces to pass
  to lxc.hook.stop. This list duplicated inherited file descriptors.

Let's simply use a single list in the handler that has all file descriptors we
need and get rid of all other ones. As an illustration. Starting a container

1. Without this patch and looking at the fds that the monitor keeps open (26):

chb@conventiont|~
> ls -al /proc/27219/fd
total 0
dr-x------ 2 root root  0 Oct 29 14:30 .
dr-xr-xr-x 9 root root  0 Oct 29 14:30 ..
lrwx------ 1 root root 64 Oct 29 14:30 0 -> /dev/null
lrwx------ 1 root root 64 Oct 29 14:30 1 -> /dev/null
lrwx------ 1 root root 64 Oct 29 14:30 10 -> anon_inode:[signalfd]
lrwx------ 1 root root 64 Oct 29 14:30 11 -> /dev/ptmx
lrwx------ 1 root root 64 Oct 29 14:30 12 -> /dev/pts/10
lr-x------ 1 root root 64 Oct 29 14:30 13 -> net:[4026532553]
lrwx------ 1 root root 64 Oct 29 14:30 15 -> socket:[7909181]
lrwx------ 1 root root 64 Oct 29 14:30 16 -> socket:[7909182]
lr-x------ 1 root root 64 Oct 29 14:30 17 -> uts:[4026531838]
lr-x------ 1 root root 64 Oct 29 14:30 18 -> ipc:[4026531839]
lr-x------ 1 root root 64 Oct 29 14:30 19 -> net:[4026532009]
lrwx------ 1 root root 64 Oct 29 14:30 2 -> /dev/null
lr-x------ 1 root root 64 Oct 29 14:30 20 -> mnt:[4026532611]
lr-x------ 1 root root 64 Oct 29 14:30 21 -> pid:[4026532612]
lr-x------ 1 root root 64 Oct 29 14:30 22 -> uts:[4026532548]
lr-x------ 1 root root 64 Oct 29 14:30 23 -> ipc:[4026532549]
lr-x------ 1 root root 64 Oct 29 14:30 24 -> net:[4026532553]
l-wx------ 1 root root 64 Oct 29 14:30 3 -> /var/log/lxc/a1.log
lr-x------ 1 root root 64 Oct 29 14:30 4 -> uts:[4026532548]
lr-x------ 1 root root 64 Oct 29 14:30 5 -> ipc:[4026532549]
lr-x------ 1 root root 64 Oct 29 14:30 6 -> net:[4026532553]
lrwx------ 1 root root 64 Oct 29 14:30 7 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Oct 29 14:30 9 -> socket:[7911594]

2. With this patch and looking at the fds that the monitor keeps open (19):

chb@conventiont|~
> ls -al /proc/28465/fd
total 0
dr-x------ 2 root root  0 Oct 29 14:31 .
dr-xr-xr-x 9 root root  0 Oct 29 14:31 ..
lrwx------ 1 root root 64 Oct 29 14:31 0 -> /dev/null
lrwx------ 1 root root 64 Oct 29 14:31 1 -> /dev/null
lr-x------ 1 root root 64 Oct 29 14:31 10 -> net:[4026532820]
lrwx------ 1 root root 64 Oct 29 14:31 12 -> socket:[7912349]
lrwx------ 1 root root 64 Oct 29 14:31 13 -> socket:[7912350]
lr-x------ 1 root root 64 Oct 29 14:31 14 -> mnt:[4026532611]
lr-x------ 1 root root 64 Oct 29 14:31 15 -> pid:[4026532813]
lr-x------ 1 root root 64 Oct 29 14:31 16 -> uts:[4026532612]
lr-x------ 1 root root 64 Oct 29 14:31 17 -> ipc:[4026532613]
lr-x------ 1 root root 64 Oct 29 14:31 18 -> net:[4026532820]
lrwx------ 1 root root 64 Oct 29 14:31 2 -> /dev/null
l-wx------ 1 root root 64 Oct 29 14:31 3 -> /var/log/lxc/a1.log
lrwx------ 1 root root 64 Oct 29 14:31 4 -> anon_inode:[signalfd]
lrwx------ 1 root root 64 Oct 29 14:31 5 -> /dev/ptmx
lrwx------ 1 root root 64 Oct 29 14:31 6 -> /dev/pts/10
lrwx------ 1 root root 64 Oct 29 14:31 7 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Oct 29 14:31 9 -> socket:[7913041]

Relates to #1881.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/confile_utils.c
src/lxc/confile_utils.h
src/lxc/namespace.c
src/lxc/namespace.h
src/lxc/network.c
src/lxc/start.c
src/lxc/start.h
src/lxc/tools/lxc_start.c

index 8a66f2d02ca50a9a212faca9383633855fb7d768..2cea7c4a310338ea729f982704c3f98ddbe64cd0 100644 (file)
@@ -2461,21 +2461,19 @@ 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));
+       memset(&new->inherit_ns, 0, sizeof(char *) * LXC_NS_MAX);
 
        return new;
 }
@@ -3155,7 +3153,7 @@ int lxc_setup_child(struct lxc_handler *handler)
                return -1;
        }
 
-       if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
+       if (handler->nsfd[LXC_NS_UTS] == -1) {
                if (setup_utsname(lxc_conf->utsname)) {
                        ERROR("failed to setup the utsname for '%s'", name);
                        return -1;
index 63e71e2d84f1939ccbb3d9a052ae75a6e760ea73..063b589808b624ed2012e36a9013973f307804dd 100644 (file)
@@ -285,8 +285,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 +346,8 @@ struct lxc_conf {
         * that union.
         */
        struct lxc_cgroup cgroup_meta;
+
+       char *inherit_ns[LXC_NS_MAX];
 };
 
 #ifdef HAVE_TLS
index d94a307191fc586acd97f81ed1a5e272110b4f55..c4d4c23945374dfafb6328f133589cd738696a2a 100644 (file)
@@ -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);
+}
+
 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]);
+
+       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,23 @@ 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]);
+       lxc_conf->inherit_ns[ns_idx] = NULL;
+
+       return 0;
+}
+
 static int get_config_includefiles(const char *key, char *retv, int inlen,
                                   struct lxc_conf *c, void *data)
 {
index 9db4bc6d3711e68294a55f001af6c0c06eb9cb47..3d843ba77800eb5093b27f1d232280cc729081e3 100644 (file)
@@ -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,77 @@ 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(const char *lxcname_or_pid, const char *lxcpath,
+                         const char *namespace)
+{
+       int fd, pid;
+       char *dup, *lastslash;
+
+       lastslash = strrchr(lxcname_or_pid, '/');
+       if (lastslash) {
+               dup = strdup(lxcname_or_pid);
+               if (!dup)
+                       return -ENOMEM;
+
+               *lastslash = '\0';
+               pid = lxc_container_name_to_pid(lastslash, dup);
+               free(dup);
+       } else {
+               pid = lxc_container_name_to_pid(lxcname_or_pid, lxcpath);
+       }
+
+       if (pid < 0)
+               return -EINVAL;
+
+       fd = lxc_preserve_ns(pid, namespace);
+       if (fd < 0)
+               return -EINVAL;
+
+       return fd;
+}
index ee9376e247908d37b093d3a8abee2eaf5f9bea42..33822faf2d2175de3ff063cd1b530fa97a6fb83c 100644 (file)
@@ -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(const char *lxcname_or_pid,
+                                const char *lxcpath, const char *namespace);
 
 #endif /* __LXC_CONFILE_UTILS_H */
index e760c0d9a0ff37eaea5871b638d7c2e788b7fbe4..da434052ae889c28d0c7eb54a58417798f7d75f5 100644 (file)
@@ -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)
index 4916950c15d2a0e935cafd610f140ae2fcd7ed75..02ec08885d0ee9bfc6cfe028709ac7191f69d97e 100644 (file)
@@ -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
index da62594478e2a64627570b6bdb65b47774b63af2..c0ca99d40e63b60ce0a9c524b0fe4ea752345b6a 100644 (file)
@@ -2302,14 +2302,14 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
 
        *netns_path = '\0';
 
-       if (handler->netnsfd < 0) {
+       if (handler->nsfd[LXC_NS_NET] < 0) {
                DEBUG("Cannot not guarantee safe deletion of network devices. "
                      "Manual cleanup maybe needed");
                return false;
        }
 
        ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d",
-                      getpid(), handler->netnsfd);
+                      getpid(), handler->nsfd[LXC_NS_NET]);
        if (ret < 0 || ret >= sizeof(netns_path))
                return false;
 
@@ -2621,7 +2621,7 @@ int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
        int oldfd;
        char ifname[IFNAMSIZ];
        struct lxc_list *iterator;
-       int netnsfd = handler->netnsfd;
+       int netnsfd = handler->nsfd[LXC_NS_NET];
        struct lxc_conf *conf = handler->conf;
 
        /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
index e3827c2b7320a182b34d579027f5502d791a50b9..ee8a4551eb6dec9b8f7de60017a7b790abdc7ea8 100644 (file)
@@ -155,6 +155,7 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid)
        for (i = 0; i < LXC_NS_MAX; i++) {
                if ((clone_flags & ns_info[i].clone_flag) == 0)
                        continue;
+
                ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
                if (ns_fd[i] < 0)
                        goto error;
@@ -236,15 +237,6 @@ restart:
                    (i < len_fds && fd == fds_to_ignore[i]))
                        continue;
 
-               if (conf) {
-                       for (i = 0; i < LXC_NS_MAX; i++)
-                               if (conf->inherit_ns_fd[i] == fd)
-                                       break;
-
-                       if (i < LXC_NS_MAX)
-                               continue;
-               }
-
                if (current_config && fd == current_config->logfd)
                        continue;
 
@@ -254,10 +246,10 @@ restart:
                if (closeall) {
                        close(fd);
                        closedir(dir);
-                       INFO("Closed inherited fd: %d.", fd);
+                       INFO("Closed inherited fd %d", fd);
                        goto restart;
                }
-               WARN("Inherited fd: %d.", fd);
+               WARN("Inherited fd %d", fd);
        }
 
        /* Only enable syslog at this point to avoid the above logging function
@@ -722,16 +714,13 @@ 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->nsfd[i] < 0)
+                       continue;
 
-       if (handler->netnsfd >= 0) {
-               close(handler->netnsfd);
-               handler->netnsfd = -1;
+               close(handler->nsfd[i]);
+               handler->nsfd[i] = -1;
        }
 
        cgroup_destroy(handler);
@@ -1123,27 +1112,27 @@ 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]) {
                if (!lxc_requests_empty_network(handler))
                        handler->clone_flags |= CLONE_NEWNET;
        } else {
-               INFO("Inheriting a NET namespace.");
+               INFO("Inheriting net namespace");
        }
 
-       if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1)
+       if (!handler->conf->inherit_ns[LXC_NS_IPC])
                handler->clone_flags |= CLONE_NEWIPC;
        else
-               INFO("Inheriting an IPC namespace.");
+               INFO("Inheriting ipc namespace");
 
-       if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1)
+       if (!handler->conf->inherit_ns[LXC_NS_UTS])
                handler->clone_flags |= CLONE_NEWUTS;
        else
-               INFO("Inheriting a UTS namespace.");
+               INFO("Inheriting uts namespace");
 
-       if (handler->conf->inherit_ns_fd[LXC_NS_PID] == -1)
+       if (!handler->conf->inherit_ns[LXC_NS_PID])
                handler->clone_flags |= CLONE_NEWPID;
        else
-               INFO("Inheriting a PID namespace.");
+               INFO("Inheriting pid namespace");
 }
 
 /* lxc_spawn() performs crucial setup tasks and clone()s the new process which
@@ -1162,15 +1151,24 @@ static int lxc_spawn(struct lxc_handler *handler)
        struct lxc_list *id_map;
        int preserve_mask = 0;
        const char *name = handler->name;
+       const char *lxcpath = handler->lxcpath;
        bool cgroups_connected = false;
+       struct lxc_conf *conf = handler->conf;
 
-       id_map = &handler->conf->id_map;
+       id_map = &conf->id_map;
        wants_to_map_ids = !lxc_list_empty(id_map);
        memset(saved_ns_fd, -1, sizeof(int) * LXC_NS_MAX);
 
-       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++) {
+               if (!conf->inherit_ns[i])
+                       continue;
+
+               preserve_mask |= ns_info[i].clone_flag;
+
+               handler->nsfd[i] = lxc_inherit_namespace(conf->inherit_ns[i], lxcpath, ns_info[i].proc_name);
+               if (handler->nsfd[i] < 0)
+                       return -1;
+       }
 
        if (lxc_sync_init(handler))
                return -1;
@@ -1185,7 +1183,7 @@ static int lxc_spawn(struct lxc_handler *handler)
        resolve_clone_flags(handler);
 
        if (handler->clone_flags & CLONE_NEWNET) {
-               if (!lxc_list_empty(&handler->conf->network)) {
+               if (!lxc_list_empty(&conf->network)) {
 
                        /* Find gateway addresses from the link device, which is
                         * no longer accessible inside the container. Do this
@@ -1226,16 +1224,24 @@ static int lxc_spawn(struct lxc_handler *handler)
         * If the container is unprivileged then skip rootfs pinning.
         */
        if (!wants_to_map_ids) {
-               handler->pinfd = pin_rootfs(handler->conf->rootfs.path);
+               handler->pinfd = pin_rootfs(conf->rootfs.path);
                if (handler->pinfd == -1)
                        INFO("Failed to pin the rootfs for container \"%s\".", handler->name);
        }
 
        if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
                goto out_delete_net;
+       else
+               TRACE("Preserved inherited namespaces");
 
-       if (attach_ns(handler->conf->inherit_ns_fd) < 0)
-               goto out_delete_net;
+       for (i = 0; i < LXC_NS_MAX; i++) {
+               if (handler->nsfd[i] < 0)
+                       continue;
+
+               ret = setns(handler->nsfd[i], 0);
+               if (ret < 0)
+                       goto out_delete_net;
+       }
 
        /* Create a process in a new set of namespaces. */
        flags = handler->clone_flags;
@@ -1260,13 +1266,17 @@ static int lxc_spawn(struct lxc_handler *handler)
 
        for (i = 0; i < LXC_NS_MAX; i++)
                if (flags & ns_info[i].clone_flag)
-                       INFO("Cloned %s.", ns_info[i].flag_name);
+                       INFO("Cloned %s", ns_info[i].flag_name);
 
-       if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid))
-               INFO("Failed to preserve namespace for lxc.hook.stop.");
+       if (!preserve_ns(handler->nsfd, handler->clone_flags, handler->pid)) {
+               ERROR("Failed to preserve cloned namespaces for lxc.hook.stop");
+               goto out_delete_net;
+       }
 
-       if (attach_ns(saved_ns_fd))
-               WARN("Failed to restore saved namespaces.");
+       if (attach_ns(saved_ns_fd)) {
+               ERROR("Failed to restore saved namespaces");
+               goto out_delete_net;
+       }
 
        lxc_sync_fini_child(handler);
 
@@ -1302,24 +1312,18 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (!cgroup_chown(handler))
                goto out_delete_net;
 
-       handler->netnsfd = lxc_preserve_ns(handler->pid, "net");
-       if (handler->netnsfd < 0) {
-               ERROR("Failed to preserve network namespace");
-               goto out_delete_net;
-       }
-
        /* Create the network configuration. */
        if (handler->clone_flags & CLONE_NEWNET) {
                if (lxc_network_move_created_netdev_priv(handler->lxcpath,
                                                         handler->name,
-                                                        &handler->conf->network,
+                                                        &conf->network,
                                                         handler->pid)) {
                        ERROR("Failed to create the configured network.");
                        goto out_delete_net;
                }
 
                if (lxc_create_network_unpriv(handler->lxcpath, handler->name,
-                                             &handler->conf->network,
+                                             &conf->network,
                                              handler->pid)) {
                        ERROR("Failed to create the configured network.");
                        goto out_delete_net;
@@ -1337,7 +1341,7 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
                goto out_delete_net;
 
-       if (!lxc_list_empty(&handler->conf->limits) && setup_resource_limits(&handler->conf->limits, handler->pid)) {
+       if (!lxc_list_empty(&conf->limits) && setup_resource_limits(&conf->limits, handler->pid)) {
                ERROR("failed to setup resource limits for '%s'", name);
                goto out_delete_net;
        }
@@ -1359,7 +1363,7 @@ static int lxc_spawn(struct lxc_handler *handler)
                SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
 
        /* Run any host-side start hooks */
-       if (run_lxc_hooks(name, "start-host", handler->conf, handler->lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "start-host", conf, handler->lxcpath, NULL)) {
                ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
                return -1;
        }
@@ -1384,7 +1388,7 @@ static int lxc_spawn(struct lxc_handler *handler)
         * been recorded. The corresponding structs have now all been filled. So
         * log them for debugging purposes.
         */
-       lxc_log_configured_netdevs(handler->conf);
+       lxc_log_configured_netdevs(conf);
 
        /* Read tty fds allocated by child. */
        if (lxc_recv_ttys_from_child(handler) < 0) {
@@ -1428,11 +1432,6 @@ out_abort:
                handler->pinfd = -1;
        }
 
-       if (handler->netnsfd >= 0) {
-               close(handler->netnsfd);
-               handler->netnsfd = -1;
-       }
-
        return -1;
 }
 
@@ -1451,7 +1450,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
        handler->ops = ops;
        handler->data = data;
        handler->backgrounded = backgrounded;
-       handler->netnsfd = -1;
 
        if (!attach_block_device(handler->conf)) {
                ERROR("Failed to attach block device.");
index be724bcaf5190cf6d82fb9c41c00c126b6434f54..c6732269390b7fa3590a4c59b8e2a71ab0b57bac 100644 (file)
@@ -40,9 +40,6 @@ struct lxc_handler {
        /* The clone flags that were requested. */
        int clone_flags;
 
-       /* File descriptors referring to the network namespace of the container. */
-       int netnsfd;
-
        /* File descriptor to pin the rootfs for privileged containers. */
        int pinfd;
 
index 69e00471e473d5b24826495ff7febd4e7cf9b343..356f704303b76096b7da391dd0eee5085403e80c 100644 (file)
@@ -89,53 +89,6 @@ err:
        return err;
 }
 
-static int pid_from_lxcname(const char *lxcname_or_pid, const char *lxcpath) {
-       char *eptr;
-       int pid = strtol(lxcname_or_pid, &eptr, 10);
-       if (*eptr != '\0' || pid < 1) {
-               struct lxc_container *s;
-               s = lxc_container_new(lxcname_or_pid, lxcpath);
-               if (!s) {
-                       SYSERROR("'%s' is not a valid pid nor a container name", lxcname_or_pid);
-                       return -1;
-               }
-
-               if (!s->may_control(s)) {
-                       SYSERROR("Insufficient privileges to control container '%s'", s->name);
-                       lxc_container_put(s);
-                       return -1;
-               }
-
-               pid = s->init_pid(s);
-               if (pid < 1) {
-                       SYSERROR("Is container '%s' running?", s->name);
-                       lxc_container_put(s);
-                       return -1;
-               }
-
-               lxc_container_put(s);
-       }
-       if (kill(pid, 0) < 0) {
-               SYSERROR("Can't send signal to pid %d", pid);
-               return -1;
-       }
-
-       return pid;
-}
-
-static int open_ns(int pid, const char *ns_proc_name) {
-       int fd;
-       char path[MAXPATHLEN];
-       snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns_proc_name);
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0) {
-               SYSERROR("failed to open %s", path);
-               return -1;
-       }
-       return fd;
-}
-
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
        switch (c) {
@@ -201,16 +154,18 @@ Options :\n\
 
 int main(int argc, char *argv[])
 {
-       int err = EXIT_FAILURE;
+       int i;
        struct lxc_conf *conf;
        struct lxc_log log;
+       const char *lxcpath;
        char *const *args;
+       struct lxc_container *c;
+       int err = EXIT_FAILURE;
        char *rcfile = NULL;
        char *const default_args[] = {
                "/sbin/init",
                NULL,
        };
-       struct lxc_container *c;
 
        lxc_list_init(&defines);
 
@@ -236,14 +191,13 @@ int main(int argc, char *argv[])
                exit(err);
        lxc_log_options_no_override();
 
-       if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
+       lxcpath = my_args.lxcpath[0];
+       if (access(lxcpath, O_RDONLY) < 0) {
                if (!my_args.quiet)
-                       fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
+                       fprintf(stderr, "You lack access to %s\n", lxcpath);
                exit(err);
        }
 
-       const char *lxcpath = my_args.lxcpath[0];
-
        /* REMOVE IN LXC 3.0 */
        setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
 
@@ -333,19 +287,26 @@ int main(int argc, char *argv[])
                }
        }
 
-       int i;
        for (i = 0; i < LXC_NS_MAX; i++) {
-               if (my_args.share_ns[i] == NULL)
+               const char *key, *value;
+
+               value = my_args.share_ns[i];
+               if (!value)
                        continue;
 
-               int pid = pid_from_lxcname(my_args.share_ns[i], lxcpath);
-               if (pid < 1)
-                       goto out;
+               if (i == LXC_NS_NET)
+                       key = "lxc.namespace.net";
+               else if (i == LXC_NS_IPC)
+                       key = "lxc.namespace.ipc";
+               else if (i == LXC_NS_UTS)
+                       key = "lxc.namespace.uts";
+               else if (i == LXC_NS_PID)
+                       key = "lxc.namespace.pid";
+               else
+                       continue;
 
-               int fd = open_ns(pid, ns_info[i].proc_name);
-               if (fd < 0)
+               if (!c->set_config_item(c, key, value))
                        goto out;
-               conf->inherit_ns_fd[i] = fd;
        }
 
        if (!my_args.daemonize) {