2aa73e93 |
From: Serge Hallyn <serge.hallyn@canonical.com>
Date: Fri, 31 May 2013 19:12:12 +0000 (+0100)
Subject: add sysctl to disallow unprivileged CLONE_NEWUSER by default
Origin: http://kernel.ubuntu.com/git?p=serge%2Fubuntu-saucy.git;a=commit;h=5c847404dcb2e3195ad0057877e1422ae90892b8
add sysctl to disallow unprivileged CLONE_NEWUSER by default
This is a short-term patch. Unprivileged use of CLONE_NEWUSER
is certainly an intended feature of user namespaces. However
for at least saucy we want to make sure that, if any security
issues are found, we have a fail-safe.
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
[bwh: Remove unneeded binary sysctl bits] |
bc415e79 |
[Srivatsa: Fix capability checks when running nested user namespaces by
using ns_capable() on the current task's user namespace.]
Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu>
diff --git a/kernel/fork.c b/kernel/fork.c
index 9321b1a..34d50a6 100644 |
2aa73e93 |
--- a/kernel/fork.c
+++ b/kernel/fork.c |
bc415e79 |
@@ -88,6 +88,11 @@ |
2aa73e93 |
#define CREATE_TRACE_POINTS
#include <trace/events/task.h>
+#ifdef CONFIG_USER_NS
+extern int unprivileged_userns_clone;
+#else
+#define unprivileged_userns_clone 0
+#endif
/*
* Minimum number of threads to boot the kernel |
bc415e79 |
@@ -1476,6 +1481,10 @@ static __latent_entropy struct task_struct *copy_process( |
2aa73e93 |
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
return ERR_PTR(-EINVAL);
+ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) |
bc415e79 |
+ if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
2aa73e93 |
+ return ERR_PTR(-EPERM);
+
/*
* Thread groups must share signals as well, and detached threads
* can only be started up within the thread group. |
bc415e79 |
@@ -2216,6 +2225,12 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) |
2aa73e93 |
if (unshare_flags & CLONE_NEWNS)
unshare_flags |= CLONE_FS;
+ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
+ err = -EPERM; |
bc415e79 |
+ if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
2aa73e93 |
+ goto bad_unshare_out;
+ }
+
err = check_unshare_flags(unshare_flags);
if (err)
goto bad_unshare_out; |
bc415e79 |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8dc9e80..0d91b8e 100644 |
2aa73e93 |
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c |
bc415e79 |
@@ -104,6 +104,9 @@ extern int core_uses_pid; |
2aa73e93 |
extern char core_pattern[];
extern unsigned int core_pipe_limit;
#endif
+#ifdef CONFIG_USER_NS
+extern int unprivileged_userns_clone;
+#endif
extern int pid_max;
extern int pid_max_min, pid_max_max;
extern int percpu_pagelist_fraction; |
bc415e79 |
@@ -504,6 +507,15 @@ static struct ctl_table kern_table[] = { |
2aa73e93 |
.proc_handler = proc_dointvec,
}, |
bc415e79 |
#endif |
2aa73e93 |
+#ifdef CONFIG_USER_NS
+ {
+ .procname = "unprivileged_userns_clone",
+ .data = &unprivileged_userns_clone,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ }, |
bc415e79 |
+#endif |
2aa73e93 |
#ifdef CONFIG_PROC_SYSCTL
{ |
bc415e79 |
.procname = "tainted",
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 86b7854..4e2e171 100644 |
2aa73e93 |
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -23,6 +23,9 @@
#include <linux/projid.h>
#include <linux/fs_struct.h>
+/* sysctl */
+int unprivileged_userns_clone;
+
static struct kmem_cache *user_ns_cachep __read_mostly;
static DEFINE_MUTEX(userns_state_mutex);
|