]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc-attach: Detect which namespaces to attach to dynamically
authorChristian Seiler <christian@iwakd.de>
Tue, 21 Aug 2012 22:03:13 +0000 (00:03 +0200)
committerStéphane Graber <stgraber@ubuntu.com>
Mon, 12 Nov 2012 18:13:52 +0000 (13:13 -0500)
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 <christian@iwakd.de>
Cc: Daniel Lezcano <daniel.lezcano@free.fr>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
src/lxc/attach.c
src/lxc/attach.h
src/lxc/lxc_attach.c

index a95b3d3cce7ab5bb282484662e9f0325ce6af030..37e667fe1c194aa4319b7f23e412349b17164abb 100644 (file)
@@ -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;
                }
index 2d46c83dcc014d786210ad6570df4a6c94a9f8a3..d96fdae42e1571a9a0bb7a221628a3de180b6d2f 100644 (file)
@@ -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
index e4f604ba329fc83ff3db66294e522081fde3659b..10d4a64ad7e43e7dc7329af1867b0d1efcbc7c7b 100644 (file)
@@ -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;