summaryrefslogtreecommitdiffstats
path: root/net/core/net_namespace.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-12-14 07:55:36 -0800
committerEric W. Biederman <ebiederm@xmission.com>2012-12-14 16:12:03 -0800
commit5e4a08476b50fa39210fca82e03325cc46b9c235 (patch)
treefb3a3c6b4c3f613abf354adefcff8a74051acdce /net/core/net_namespace.c
parent520d9eabce18edfef76a60b7b839d54facafe1f9 (diff)
downloadlinux-5e4a08476b50fa39210fca82e03325cc46b9c235.tar.gz
linux-5e4a08476b50fa39210fca82e03325cc46b9c235.tar.bz2
linux-5e4a08476b50fa39210fca82e03325cc46b9c235.zip
userns: Require CAP_SYS_ADMIN for most uses of setns.
Andy Lutomirski <luto@amacapital.net> found a nasty little bug in the permissions of setns. With unprivileged user namespaces it became possible to create new namespaces without privilege. However the setns calls were relaxed to only require CAP_SYS_ADMIN in the user nameapce of the targed namespace. Which made the following nasty sequence possible. pid = clone(CLONE_NEWUSER | CLONE_NEWNS); if (pid == 0) { /* child */ system("mount --bind /home/me/passwd /etc/passwd"); } else if (pid != 0) { /* parent */ char path[PATH_MAX]; snprintf(path, sizeof(path), "/proc/%u/ns/mnt"); fd = open(path, O_RDONLY); setns(fd, 0); system("su -"); } Prevent this possibility by requiring CAP_SYS_ADMIN in the current user namespace when joing all but the user namespace. Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'net/core/net_namespace.c')
-rw-r--r--net/core/net_namespace.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2e9a3132b8dd..8acce01b6dab 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -649,7 +649,8 @@ static int netns_install(struct nsproxy *nsproxy, void *ns)
{
struct net *net = ns;
- if (!ns_capable(net->user_ns, CAP_SYS_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||
+ !nsown_capable(CAP_SYS_ADMIN))
return -EPERM;
put_net(nsproxy->net_ns);