[PATCH][SRU T, U, V] UBUNTU: SAUCE: add a sysctl to disable unprivileged user namespace unsharing

Kamal Mostafa kamal at canonical.com
Thu Jun 23 18:53:57 UTC 2016


From: Serge Hallyn <serge.hallyn at ubuntu.com>

BugLink: https://bugs.launchpad.net/bugs/1595350

It is turned on by default, but can be turned off if admins prefer or,
more importantly, if a security vulnerability is found.

The intent is to use this as mitigation so long as Ubuntu is on the
cutting edge of enablement for things like unprivileged filesystem
mounting.

(This patch is tweaked from the one currently still in Debian sid, which
in turn came from the patch we had in saucy)

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
[bwh: Remove unneeded binary sysctl bits]
Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 kernel/fork.c           | 15 +++++++++++++++
 kernel/sysctl.c         | 12 ++++++++++++
 kernel/user_namespace.c |  6 ++++++
 3 files changed, 33 insertions(+)

diff --git a/kernel/fork.c b/kernel/fork.c
index f5e5831..937c7a1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -83,6 +83,11 @@
 
 #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
 
 /*
  * Protected counters by write_lock_irq(&tasklist_lock)
@@ -1190,6 +1195,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
 		return ERR_PTR(-EINVAL);
 
+	if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
+		if (!capable(CAP_SYS_ADMIN))
+			return ERR_PTR(-EPERM);
+
 	/*
 	 * Thread groups must share signals as well, and detached threads
 	 * can only be started up within the thread group.
@@ -1897,6 +1906,12 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 	if (unshare_flags & CLONE_NEWNS)
 		unshare_flags |= CLONE_FS;
 
+	if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
+		err = -EPERM;
+		if (!capable(CAP_SYS_ADMIN))
+			goto bad_unshare_out;
+	}
+
 	err = check_unshare_flags(unshare_flags);
 	if (err)
 		goto bad_unshare_out;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 09e750e..b0bac2e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -106,6 +106,9 @@ extern int core_uses_pid;
 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;
@@ -532,6 +535,15 @@ static struct ctl_table kern_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 #endif
+#ifdef CONFIG_USER_NS
+	{
+		.procname	= "unprivileged_userns_clone",
+		.data		= &unprivileged_userns_clone,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#endif
 #ifdef CONFIG_PROC_SYSCTL
 	{
 		.procname	= "tainted",
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 722bd12..0842a49 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -23,6 +23,12 @@
 #include <linux/projid.h>
 #include <linux/fs_struct.h>
 
+/*
+ * sysctl determining whether unprivileged users may unshare a new
+ * userns.  Allowed by default
+ */
+int unprivileged_userns_clone = 1;
+
 static struct kmem_cache *user_ns_cachep __read_mostly;
 static DEFINE_MUTEX(userns_state_mutex);
 
-- 
2.7.4





More information about the kernel-team mailing list