SPECS/linux/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch
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);