From 29ed9c13ac360aa5b053f935cee09ef62619ee20 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 20 Nov 2016 06:20:07 +0100 Subject: [PATCH] namespace: always attach to user namespace first Move the user namespace at the first position in the array so that we always attach to it first when iterating over the struct and using setns() to switch namespaces. This especially affects lxc_attach(): Suppose you cloned a new user namespace and mount namespace as an unprivileged user on the host and want to setns() to the mount namespace. This requires you to attach to the user namespace first otherwise the kernel will fail this check: if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || !ns_capable(current_user_ns(), CAP_SYS_CHROOT) || !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) return -EPERM; in linux/fs/namespace.c:mntns_install(). Signed-off-by: Christian Brauner --- src/lxc/namespace.c | 18 +++++++++++++++++- src/lxc/namespace.h | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c index bb76f4c90..3a5b3bef6 100644 --- a/src/lxc/namespace.c +++ b/src/lxc/namespace.c @@ -69,12 +69,28 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags) return ret; } +/* Leave the user namespace at the first position in the array of structs so + * that we always attach to it first when iterating over the struct and using + * setns() to switch namespaces. This especially affects lxc_attach(): Suppose + * you cloned a new user namespace and mount namespace as an unprivileged user + * on the host and want to setns() to the mount namespace. This requires you to + * attach to the user namespace first otherwise the kernel will fail this check: + * + * if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || + * !ns_capable(current_user_ns(), CAP_SYS_CHROOT) || + * !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) + * return -EPERM; + * + * in + * + * linux/fs/namespace.c:mntns_install(). + */ const struct ns_info ns_info[LXC_NS_MAX] = { + [LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"}, [LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"}, [LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"}, [LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"}, [LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"}, - [LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"}, [LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"}, [LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"} }; diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h index 57167f4d0..4916950c1 100644 --- a/src/lxc/namespace.h +++ b/src/lxc/namespace.h @@ -54,11 +54,11 @@ #endif enum { + LXC_NS_USER, LXC_NS_MNT, LXC_NS_PID, LXC_NS_UTS, LXC_NS_IPC, - LXC_NS_USER, LXC_NS_NET, LXC_NS_CGROUP, LXC_NS_MAX -- 2.47.2