When attaching to only some namespaces of the container but not the mount
namespace, the contents of /sys and /proc of the host system do not properly
reflect the context of the container's pid and/or network namespaces, and
possibly others.

The introduced -R option adds the possibility to additionally unshare the
mount namespace (when it is not being attached) and remount /sys and /proc
in order for those filesystems to properly reflect the container's context
even when only attaching to some of the namespaces.

Signed-off-by: Christian Seiler <christ...@iwakd.de>
Cc: Stéphane Graber <stgra...@ubuntu.com>
Cc: Daniel Lezcano <daniel.lezc...@free.fr>
Cc: Serge Hallyn <serge.hal...@canonical.com>
---
 doc/lxc-attach.sgml.in |   42 ++++++++++++++++++++++++++++++++++--------
 src/lxc/attach.c       |   44 ++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/attach.h       |    1 +
 src/lxc/lxc_attach.c   |   27 ++++++++++++++++++++++++++-
 4 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/doc/lxc-attach.sgml.in b/doc/lxc-attach.sgml.in
index d7fb223..1d7684e 100644
--- a/doc/lxc-attach.sgml.in
+++ b/doc/lxc-attach.sgml.in
@@ -50,7 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307 USA
     <cmdsynopsis><command>lxc-attach <replaceable>-n
     name</replaceable> <optional>-a
     arch</optional> <optional>-e</optional> <optional>-s
-    namespaces</optional>
+    namespaces</optional> <optional>-R</optional>
     <optional>-- command</optional></command></cmdsynopsis>
   </refsynopsisdiv>
 
@@ -146,6 +146,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307 USA
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+       <term>
+         <option>-R, --remount-sys-proc</option>
+       </term>
+       <listitem>
+         <para>
+           When using <option>-s</option> and the mount namespace is not
+           included, this flag will cause <command>lxc-attach</command>
+           to remount <replaceable>/proc</replaceable> and
+           <replaceable>/sys</replaceable> to reflect the current other
+           namespace contexts.
+         </para>
+         <para>
+           Please see the <emphasis>Notes</emphasis> section for more
+           details.
+         </para>
+         <para>
+           This option will be ignored if one tries to attach to the
+           mount namespace anyway.
+         </para>
+       </listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>
@@ -230,13 +253,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307 USA
       the network namespace.
     </para>
     <para>
-      A workaround is to use <command>lxc-unshare</command> to unshare
-      the mount namespace after using <command>lxc-attach</command> with
-      <replaceable>-s PID</replaceable> and/or <replaceable>-s
-      NETWORK</replaceable> and then unmount and then mount again both
-      pseudo-filesystems within that new mount namespace, before
-      executing a program/script that relies on this information to be
-      correct.
+      To work around this problem, the <option>-R</option> flag provides
+      the option to remount <replaceable>/proc</replaceable> and
+      <replaceable>/sys</replaceable> in order for them to reflect the
+      network/pid namespace context of the attached process. In order
+      not to interfere with the host's actual filesystem, the mount
+      namespace will be unshared (like <command>lxc-unshare</command>
+      does) before this is done, esentially giving the process a new
+      mount namespace, which is identical to the hosts's mount namespace
+      except for the <replaceable>/proc</replaceable> and
+      <replaceable>/sys</replaceable> filesystems.
     </para>
   </refsect1>
 
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 9d598f0..2ae9587 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 #include <sys/param.h>
 #include <sys/prctl.h>
+#include <sys/mount.h>
 #include <linux/unistd.h>
 
 #if !HAVE_DECL_PR_CAPBSET_DROP
@@ -218,6 +219,49 @@ int lxc_attach_to_ns(pid_t pid, int which)
        return 0;
 }
 
+int lxc_attach_remount_sys_proc()
+{
+       int ret;
+
+       ret = unshare(CLONE_NEWNS);
+       if (ret < 0) {
+               SYSERROR("failed to unshare mount namespace: %s", 
strerror(errno));
+               return -1;
+       }
+
+       /* assume /proc is always mounted, so remount it */
+       ret = umount2("/proc", MNT_DETACH);
+       if (ret < 0) {
+               SYSERROR("failed to unmount /proc: %s", strerror(errno));
+               return -1;
+       }
+
+       ret = mount("none", "/proc", "proc", 0, NULL);
+       if (ret < 0) {
+               SYSERROR("failed to remount /proc: %s", strerror(errno));
+               return -1;
+       }
+
+       /* try to umount /sys - if it's not a mount point,
+        * we'll get EINVAL, then we ignore it because it
+        * may not have been mounted in the first place
+        */
+       ret = umount2("/sys", MNT_DETACH);
+       if (ret < 0 && errno != EINVAL) {
+               SYSERROR("failed to unmount /sys: %s", strerror(errno));
+               return -1;
+       } else if (ret == 0) {
+               /* remount it */
+               ret = mount("none", "/sys", "sysfs", 0, NULL);
+               if (ret < 0) {
+                       SYSERROR("failed to remount /sys: %s", strerror(errno));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
 {
        int last_cap = lxc_caps_last_cap();
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index d96fdae..aab47e3 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -34,6 +34,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, int which);
+extern int lxc_attach_remount_sys_proc();
 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 6b98248..82aeb1d 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -48,18 +48,21 @@ static const struct option my_longopts[] = {
        {"elevated-privileges", no_argument, 0, 'e'},
        {"arch", required_argument, 0, 'a'},
        {"namespaces", required_argument, 0, 's'},
+       {"remount-sys-proc", no_argument, 0, 'R'},
        LXC_COMMON_OPTIONS
 };
 
 static int elevated_privileges = 0;
 static signed long new_personality = -1;
 static int namespace_flags = -1;
+static int remount_sys_proc = 0;
 
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
        int ret;
        switch (c) {
        case 'e': elevated_privileges = 1; break;
+       case 'R': remount_sys_proc = 1; break;
        case 'a':
                new_personality = lxc_config_parse_arch(arg);
                if (new_personality < 0) {
@@ -99,7 +102,12 @@ Options :\n\
                     but just to the following OR'd list of flags:\n\
                     MOUNT, PID, UTSNAME, IPC, USER or NETWORK\n\
                     WARNING: Using -s implies -e, it may therefore\n\
-                    leak privileges into the container. Use with care.",
+                    leak privileges into the container. Use with care.\n\
+  -R, --remount-sys-proc\n\
+                    Remount /sys and /proc if not attaching to the\n\
+                    mount namespace when using -s in order to properly\n\
+                    reflect the correct namespace context. See the\n\
+                    lxc-attach(1) manual page for details.\n",
        .options  = my_longopts,
        .parser   = my_parser,
        .checker  = NULL,
@@ -206,6 +214,23 @@ int main(int argc, char *argv[])
                        return -1;
                }
 
+               /* if the user wants to attach to namespaces that don't
+                * include the mount namespace, and the -R option was
+                * specified, unshare the mount namespace (but DON'T
+                * attach to that of the container) and remount /sys and
+                * /proc in that new mount namespace so that they
+                * represent the current state of the other namespaces
+                * (i.e. /sys/class/net reflects the current network
+                * namespace and /proc contents reflects the current
+                * pid namespace)
+                */
+               if (namespace_flags != -1 && !(namespace_flags & CLONE_NEWNS) 
&& remount_sys_proc) {
+                       ret = lxc_attach_remount_sys_proc();
+                       if (ret < 0) {
+                               return -1;
+                       }
+               }
+
                if (curdir && chdir(curdir))
                        WARN("could not change directory to '%s'", curdir);
 
-- 
1.7.2.5


------------------------------------------------------------------------------
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