Skip to content

Commit 09d049b

Browse files
hallynheftig
authored andcommitted
add sysctl to allow disabling unprivileged CLONE_NEWUSER
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. [bwh: Remove unneeded binary sysctl bits] [bwh: Keep this sysctl, but change the default to enabled] [heftig: correct commit subject to reduce confusion]
1 parent fc85704 commit 09d049b

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

kernel/fork.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@
119119

120120
#include <kunit/visibility.h>
121121

122+
#ifdef CONFIG_USER_NS
123+
extern int unprivileged_userns_clone;
124+
#else
125+
#define unprivileged_userns_clone 0
126+
#endif
127+
122128
/*
123129
* Minimum number of threads to boot the kernel
124130
*/
@@ -2194,6 +2200,10 @@ __latent_entropy struct task_struct *copy_process(
21942200
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
21952201
return ERR_PTR(-EINVAL);
21962202

2203+
if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
2204+
if (!capable(CAP_SYS_ADMIN))
2205+
return ERR_PTR(-EPERM);
2206+
21972207
/*
21982208
* Thread groups must share signals as well, and detached threads
21992209
* can only be started up within the thread group.
@@ -3354,6 +3364,12 @@ int ksys_unshare(unsigned long unshare_flags)
33543364
if (unshare_flags & CLONE_NEWNS)
33553365
unshare_flags |= CLONE_FS;
33563366

3367+
if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
3368+
err = -EPERM;
3369+
if (!capable(CAP_SYS_ADMIN))
3370+
goto bad_unshare_out;
3371+
}
3372+
33573373
err = check_unshare_flags(unshare_flags);
33583374
if (err)
33593375
goto bad_unshare_out;

kernel/sysctl.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
8484
static const int ngroups_max = NGROUPS_MAX;
8585
static const int cap_last_cap = CAP_LAST_CAP;
8686

87+
#ifdef CONFIG_USER_NS
88+
extern int unprivileged_userns_clone;
89+
#endif
90+
8791
#ifdef CONFIG_PROC_SYSCTL
8892

8993
/**
@@ -1595,6 +1599,15 @@ static const struct ctl_table kern_table[] = {
15951599
.mode = 0644,
15961600
.proc_handler = proc_dointvec,
15971601
},
1602+
#ifdef CONFIG_USER_NS
1603+
{
1604+
.procname = "unprivileged_userns_clone",
1605+
.data = &unprivileged_userns_clone,
1606+
.maxlen = sizeof(int),
1607+
.mode = 0644,
1608+
.proc_handler = proc_dointvec,
1609+
},
1610+
#endif
15981611
#ifdef CONFIG_PROC_SYSCTL
15991612
{
16001613
.procname = "tainted",

kernel/user_namespace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <linux/bsearch.h>
2323
#include <linux/sort.h>
2424

25+
/* sysctl */
26+
int unprivileged_userns_clone = 1;
27+
2528
static struct kmem_cache *user_ns_cachep __ro_after_init;
2629
static DEFINE_MUTEX(userns_state_mutex);
2730

0 commit comments

Comments
 (0)