mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-16 07:19:16 +00:00
lxc-attach: Add -R option to remount /sys and /proc when only partially attaching
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 <christian@iwakd.de> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Cc: Daniel Lezcano <daniel.lezcano@free.fr>
This commit is contained in:
parent
e13eeea2db
commit
7a0b0b5672
@ -53,6 +53,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
<arg choice="opt">-a <replaceable>arch</replaceable></arg>
|
<arg choice="opt">-a <replaceable>arch</replaceable></arg>
|
||||||
<arg choice="opt">-e</arg>
|
<arg choice="opt">-e</arg>
|
||||||
<arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
|
<arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
|
||||||
|
<arg choice="opt">-R</arg>
|
||||||
<arg choice="opt">-- <replaceable>command</replaceable></arg>
|
<arg choice="opt">-- <replaceable>command</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
@ -149,7 +150,30 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
</refsect1>
|
||||||
|
|
||||||
@ -232,13 +256,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
the network namespace.
|
the network namespace.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
A workaround is to use <command>lxc-unshare</command> to unshare
|
To work around this problem, the <option>-R</option> flag provides
|
||||||
the mount namespace after using <command>lxc-attach</command> with
|
the option to remount <replaceable>/proc</replaceable> and
|
||||||
<replaceable>-s PID</replaceable> and/or <replaceable>-s
|
<replaceable>/sys</replaceable> in order for them to reflect the
|
||||||
NETWORK</replaceable> and then unmount and then mount again both
|
network/pid namespace context of the attached process. In order
|
||||||
pseudo-filesystems within that new mount namespace, before
|
not to interfere with the host's actual filesystem, the mount
|
||||||
executing a program/script that relies on this information to be
|
namespace will be unshared (like <command>lxc-unshare</command>
|
||||||
correct.
|
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>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
#if !HAVE_DECL_PR_CAPBSET_DROP
|
#if !HAVE_DECL_PR_CAPBSET_DROP
|
||||||
@ -188,6 +189,49 @@ int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
return 0;
|
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 lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
|
||||||
{
|
{
|
||||||
int last_cap = lxc_caps_last_cap();
|
int last_cap = lxc_caps_last_cap();
|
||||||
|
@ -34,6 +34,7 @@ struct lxc_proc_context_info {
|
|||||||
extern struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid);
|
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_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);
|
extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,12 +48,14 @@ static const struct option my_longopts[] = {
|
|||||||
{"elevated-privileges", no_argument, 0, 'e'},
|
{"elevated-privileges", no_argument, 0, 'e'},
|
||||||
{"arch", required_argument, 0, 'a'},
|
{"arch", required_argument, 0, 'a'},
|
||||||
{"namespaces", required_argument, 0, 's'},
|
{"namespaces", required_argument, 0, 's'},
|
||||||
|
{"remount-sys-proc", no_argument, 0, 'R'},
|
||||||
LXC_COMMON_OPTIONS
|
LXC_COMMON_OPTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
static int elevated_privileges = 0;
|
static int elevated_privileges = 0;
|
||||||
static signed long new_personality = -1;
|
static signed long new_personality = -1;
|
||||||
static int namespace_flags = -1;
|
static int namespace_flags = -1;
|
||||||
|
static int remount_sys_proc = 0;
|
||||||
|
|
||||||
static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
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) {
|
switch (c) {
|
||||||
case 'e': elevated_privileges = 1; break;
|
case 'e': elevated_privileges = 1; break;
|
||||||
|
case 'R': remount_sys_proc = 1; break;
|
||||||
case 'a':
|
case 'a':
|
||||||
new_personality = lxc_config_parse_arch(arg);
|
new_personality = lxc_config_parse_arch(arg);
|
||||||
if (new_personality < 0) {
|
if (new_personality < 0) {
|
||||||
@ -102,7 +105,12 @@ Options :\n\
|
|||||||
but just to the following OR'd list of flags:\n\
|
but just to the following OR'd list of flags:\n\
|
||||||
MOUNT, PID, UTSNAME, IPC, USER or NETWORK\n\
|
MOUNT, PID, UTSNAME, IPC, USER or NETWORK\n\
|
||||||
WARNING: Using -s implies -e, it may therefore\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,
|
.options = my_longopts,
|
||||||
.parser = my_parser,
|
.parser = my_parser,
|
||||||
.checker = NULL,
|
.checker = NULL,
|
||||||
@ -253,6 +261,18 @@ int main(int argc, char *argv[])
|
|||||||
lxc_sync_fini_parent(handler);
|
lxc_sync_fini_parent(handler);
|
||||||
lxc_cgroup_dispose_attach(cgroup_data);
|
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)
|
if (new_personality < 0)
|
||||||
new_personality = init_ctx->personality;
|
new_personality = init_ctx->personality;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user