Use the command interface to contact lxc-start to receive the set of
flags passed to clone() when starting the container. This allows lxc-attach
to determine which namespaces were used for the container and select only
those to attach to.

Signed-off-by: Christian Seiler <christ...@iwakd.de>
Cc: Daniel Lezcano <daniel.lezc...@free.fr>
Cc: Serge Hallyn <serge.hal...@canonical.com>
---
 src/lxc/attach.c     |   42 +++++++++++++++++++++++++++++++++++++-----
 src/lxc/attach.h     |    2 +-
 src/lxc/lxc_attach.c |   16 +++++++++++++++-
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index a95b3d3..37e667f 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -121,13 +121,22 @@ out_error:
        return NULL;
 }
 
-int lxc_attach_to_ns(pid_t pid)
+int lxc_attach_to_ns(pid_t pid, int which)
 {
        char path[MAXPATHLEN];
-       char *ns[] = { "pid", "mnt", "net", "ipc", "uts" };
-       const int size = sizeof(ns) / sizeof(char *);
+       /* according to 
<http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
+        * the file for user namepsaces in /proc/$pid/ns will be called
+        * 'user' once the kernel supports it
+        */
+       static char *ns[] = { "mnt", "pid", "uts", "ipc", "user", "net" };
+       static int flags[] = {
+               CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
+               CLONE_NEWUSER, CLONE_NEWNET
+       };
+       static const int size = sizeof(ns) / sizeof(char *);
        int fd[size];
-       int i;
+       int i, j, saved_errno;
+
 
        snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
        if (access(path, X_OK)) {
@@ -136,16 +145,39 @@ int lxc_attach_to_ns(pid_t pid)
        }
 
        for (i = 0; i < size; i++) {
+               /* ignore if we are not supposed to attach to that
+                * namespace
+                */
+               if (which != -1 && !(which & flags[i])) {
+                       fd[i] = -1;
+                       continue;
+               }
+
                snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
                fd[i] = open(path, O_RDONLY);
                if (fd[i] < 0) {
+                       saved_errno = errno;
+
+                       /* close all already opened file descriptors before
+                        * we return an error, so we don't leak them
+                        */
+                       for (j = 0; j < i; j++)
+                               close(fd[j]);
+
+                       errno = saved_errno;
                        SYSERROR("failed to open '%s'", path);
                        return -1;
                }
        }
 
        for (i = 0; i < size; i++) {
-               if (setns(fd[i], 0)) {
+               if (fd[i] >= 0 && setns(fd[i], 0) != 0) {
+                       saved_errno = errno;
+
+                       for (j = i; j < size; j++)
+                               close(fd[j]);
+
+                       errno = saved_errno;
                        SYSERROR("failed to set namespace '%s'", ns[i]);
                        return -1;
                }
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index 2d46c83..d96fdae 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -33,7 +33,7 @@ struct lxc_proc_context_info {
 
 extern struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid);
 
-extern int lxc_attach_to_ns(pid_t other_pid);
+extern int lxc_attach_to_ns(pid_t other_pid, int which);
 extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
 
 #endif
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index e4f604b..10d4a64 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -51,6 +51,7 @@ static const struct option my_longopts[] = {
 
 static int elevated_privileges = 0;
 static signed long new_personality = -1;
+static int namespace_flags = -1;
 
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
@@ -139,11 +140,24 @@ int main(int argc, char *argv[])
 
        curdir = get_current_dir_name();
 
+       /* determine which namespaces the container was created with
+        * by asking lxc-start
+        */
+       if (namespace_flags == -1) {
+               namespace_flags = lxc_get_clone_flags(my_args.name);
+               /* call failed */
+               if (namespace_flags == -1) {
+                       ERROR("failed to automatically determine the "
+                             "namespaces which the container unshared");
+                       return -1;
+               }
+       }
+
        /* we need to attach before we fork since certain namespaces
         * (such as pid namespaces) only really affect children of the
         * current process and not the process itself
         */
-       ret = lxc_attach_to_ns(init_pid);
+       ret = lxc_attach_to_ns(init_pid, namespace_flags);
        if (ret < 0) {
                ERROR("failed to enter the namespace");
                return -1;
-- 
1.7.8.6


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to