add sysctl to disallow unprivileged CLONE_NEWUSER by default
authorSerge Hallyn <serge.hallyn@canonical.com>
Fri, 31 May 2013 18:12:12 +0000 (19:12 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Sat, 12 Aug 2017 22:09:26 +0000 (23:09 +0100)
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]

Gbp-Pq: Topic debian
Gbp-Pq: Name add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch

kernel/fork.c
kernel/sysctl.c
kernel/user_namespace.c

index d39078651943c098b5d3e4e917165dddcce58e05..49a23f428e7652d99623dfb1249102f4070771a4 100644 (file)
 
 #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
@@ -1526,6 +1531,10 @@ static __latent_entropy struct task_struct *copy_process(
        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.
@@ -2321,6 +2330,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;
index 4dfba1a76cc360f649cbe6f35b57cf9413f2f5e1..e49f0627c62628a03a6ae59ec6f178d77f8a7f14 100644 (file)
@@ -105,6 +105,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;
@@ -491,6 +494,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",
index 2f735cbe05e8aca3b8ee8a3dcc7de493f9757c05..555323178c3ceec55577fb542a96510f8a22e754 100644 (file)
@@ -24,6 +24,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);