Skip to content

Commit 2b90fe6

Browse files
hallynheftig
authored andcommitted
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 <[email protected]> [bwh: Remove unneeded binary sysctl bits] [bwh: Keep this sysctl, but change the default to enabled]
1 parent 134876e commit 2b90fe6

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
*/
@@ -2171,6 +2177,10 @@ __latent_entropy struct task_struct *copy_process(
21712177
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
21722178
return ERR_PTR(-EINVAL);
21732179

2180+
if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
2181+
if (!capable(CAP_SYS_ADMIN))
2182+
return ERR_PTR(-EPERM);
2183+
21742184
/*
21752185
* Thread groups must share signals as well, and detached threads
21762186
* can only be started up within the thread group.
@@ -3324,6 +3334,12 @@ int ksys_unshare(unsigned long unshare_flags)
33243334
if (unshare_flags & CLONE_NEWNS)
33253335
unshare_flags |= CLONE_FS;
33263336

3337+
if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
3338+
err = -EPERM;
3339+
if (!capable(CAP_SYS_ADMIN))
3340+
goto bad_unshare_out;
3341+
}
3342+
33273343
err = check_unshare_flags(unshare_flags);
33283344
if (err)
33293345
goto bad_unshare_out;

kernel/sysctl.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ static const int six_hundred_forty_kb = 640 * 1024;
100100
static const int ngroups_max = NGROUPS_MAX;
101101
static const int cap_last_cap = CAP_LAST_CAP;
102102

103+
#ifdef CONFIG_USER_NS
104+
extern int unprivileged_userns_clone;
105+
#endif
106+
103107
#ifdef CONFIG_PROC_SYSCTL
104108

105109
/**
@@ -1617,6 +1621,15 @@ static const struct ctl_table kern_table[] = {
16171621
.mode = 0644,
16181622
.proc_handler = proc_dointvec,
16191623
},
1624+
#ifdef CONFIG_USER_NS
1625+
{
1626+
.procname = "unprivileged_userns_clone",
1627+
.data = &unprivileged_userns_clone,
1628+
.maxlen = sizeof(int),
1629+
.mode = 0644,
1630+
.proc_handler = proc_dointvec,
1631+
},
1632+
#endif
16201633
#ifdef CONFIG_PROC_SYSCTL
16211634
{
16221635
.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)