--- /usr/src/linux-4.9.54-minipli/kernel/user_namespace.c	2017-10-14 12:27:08.718490316 +0200
+++ /usr/src/linux/kernel/user_namespace.c	2017-11-01 18:27:35.317843207 +0100
@@ -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);
 
@@ -76,21 +79,6 @@
 	struct ucounts *ucounts;
 	int ret, i;
 
-#ifdef CONFIG_GRKERNSEC
-	/*
-	 * This doesn't really inspire confidence:
-	 * http://marc.info/?l=linux-kernel&m=135543612731939&w=2
-	 * http://marc.info/?l=linux-kernel&m=135545831607095&w=2
-	 * Increases kernel attack surface in areas developers
-	 * previously cared little about ("low importance due
-	 * to requiring "root" capability")
-	 * To be removed when this code receives *proper* review
-	 */
-	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
-			!capable(CAP_SETGID))
-		return -EPERM;
-#endif
-
 	ret = -ENOSPC;
 	if (parent_ns->level > 32)
 		goto fail;
--- /usr/src/linux-4.9.54-minipli/kernel/fork.c	2017-10-14 12:27:08.678490299 +0200
+++ /usr/src/linux/kernel/fork.c	2017-11-01 18:27:35.292843341 +0100
@@ -88,6 +88,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
 
 /*
  * Minimum number of threads to boot the kernel
@@ -1602,6 +1607,10 @@
 	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.
@@ -2360,6 +2369,12 @@
 	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;
--- /usr/src/linux-4.9.54-minipli/kernel/sysctl.c	2017-10-14 12:27:08.704490310 +0200
+++ /usr/src/linux/kernel/sysctl.c	2017-11-01 18:27:35.306843266 +0100
@@ -103,6 +103,9 @@
 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;
@@ -527,6 +530,15 @@
 		.mode		= 0644,
 		.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
 	{
