aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-12-14 10:55:36 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-12-14 19:12:03 -0500
commit5e4a08476b50fa39210fca82e03325cc46b9c235 (patch)
treefb3a3c6b4c3f613abf354adefcff8a74051acdce
parent520d9eabce18edfef76a60b7b839d54facafe1f9 (diff)
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>
-rw-r--r--fs/namespace.c3
-rw-r--r--ipc/namespace.c3
-rw-r--r--kernel/pid_namespace.c3
-rw-r--r--kernel/utsname.c3
-rw-r--r--net/core/net_namespace.c3
5 files changed, 10 insertions, 5 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c1bbe86f4920..398a50ff2438 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2781,7 +2781,8 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns)
2781 struct path root; 2781 struct path root;
2782 2782
2783 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || 2783 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
2784 !nsown_capable(CAP_SYS_CHROOT)) 2784 !nsown_capable(CAP_SYS_CHROOT) ||
2785 !nsown_capable(CAP_SYS_ADMIN))
2785 return -EPERM; 2786 return -EPERM;
2786 2787
2787 if (fs->users != 1) 2788 if (fs->users != 1)
diff --git a/ipc/namespace.c b/ipc/namespace.c
index cf3386a51de2..7c1fa451b0b0 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -170,7 +170,8 @@ static void ipcns_put(void *ns)
170static int ipcns_install(struct nsproxy *nsproxy, void *new) 170static int ipcns_install(struct nsproxy *nsproxy, void *new)
171{ 171{
172 struct ipc_namespace *ns = new; 172 struct ipc_namespace *ns = new;
173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) 173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
174 !nsown_capable(CAP_SYS_ADMIN))
174 return -EPERM; 175 return -EPERM;
175 176
176 /* Ditch state from the old ipc namespace */ 177 /* Ditch state from the old ipc namespace */
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 560da0dab230..fdbd0cdf271a 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -325,7 +325,8 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
325 struct pid_namespace *active = task_active_pid_ns(current); 325 struct pid_namespace *active = task_active_pid_ns(current);
326 struct pid_namespace *ancestor, *new = ns; 326 struct pid_namespace *ancestor, *new = ns;
327 327
328 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN)) 328 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
329 !nsown_capable(CAP_SYS_ADMIN))
329 return -EPERM; 330 return -EPERM;
330 331
331 /* 332 /*
diff --git a/kernel/utsname.c b/kernel/utsname.c
index f6336d51d64c..08b197e8c485 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -113,7 +113,8 @@ static int utsns_install(struct nsproxy *nsproxy, void *new)
113{ 113{
114 struct uts_namespace *ns = new; 114 struct uts_namespace *ns = new;
115 115
116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) 116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
117 !nsown_capable(CAP_SYS_ADMIN))
117 return -EPERM; 118 return -EPERM;
118 119
119 get_uts_ns(ns); 120 get_uts_ns(ns);
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)
649{ 649{
650 struct net *net = ns; 650 struct net *net = ns;
651 651
652 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN)) 652 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||
653 !nsown_capable(CAP_SYS_ADMIN))
653 return -EPERM; 654 return -EPERM;
654 655
655 put_net(nsproxy->net_ns); 656 put_net(nsproxy->net_ns);