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> Acked-by: Serge Hallyn <serge.hal...@canonical.com> Cc: Daniel Lezcano <daniel.lezc...@free.fr> --- doc/lxc-attach.sgml.in | 44 +++++++++++++++++++++++++++++++++++--------- src/lxc/attach.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/lxc/attach.h | 1 + src/lxc/lxc_attach.c | 22 +++++++++++++++++++++- 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/doc/lxc-attach.sgml.in b/doc/lxc-attach.sgml.in index 035cd27..1724393 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,7 +146,30 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA </listitem> </varlistentry> - </variablelist> + <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> @@ -229,13 +252,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 37e667f..ec0e083 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 @@ -188,6 +189,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"); + return -1; + } + + /* assume /proc is always mounted, so remount it */ + ret = umount2("/proc", MNT_DETACH); + if (ret < 0) { + SYSERROR("failed to unmount /proc"); + return -1; + } + + ret = mount("none", "/proc", "proc", 0, NULL); + if (ret < 0) { + SYSERROR("failed to remount /proc"); + 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"); + return -1; + } else if (ret == 0) { + /* remount it */ + ret = mount("none", "/sys", "sysfs", 0, NULL); + if (ret < 0) { + SYSERROR("failed to remount /sys"); + 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 4f22752..e292bc4 100644 --- a/src/lxc/lxc_attach.c +++ b/src/lxc/lxc_attach.c @@ -48,12 +48,14 @@ 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) { @@ -61,6 +63,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) 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) { @@ -102,7 +105,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.\n", + 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, @@ -253,6 +261,18 @@ int main(int argc, char *argv[]) lxc_sync_fini_parent(handler); lxc_cgroup_dispose_attach(cgroup_data); + /* A description of the purpose of this functionality is + * provided in the lxc-attach(1) manual page. We have to + * remount here and not in the parent process, otherwise + * /proc may not properly reflect the new pid namespace. + */ + if (!(namespace_flags & CLONE_NEWNS) && remount_sys_proc) { + ret = lxc_attach_remount_sys_proc(); + if (ret < 0) { + return -1; + } + } + if (new_personality < 0) new_personality = init_ctx->personality; -- 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