Skip to content

Commit

Permalink
ZEN: Add sysctl and CONFIG to disallow unprivileged CLONE_NEWUSER
Browse files Browse the repository at this point in the history
Our default behavior continues to match the vanilla kernel.
  • Loading branch information
heftig committed Nov 18, 2024
1 parent adc2186 commit a256060
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/linux/user_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ static inline void set_userns_rlimit_max(struct user_namespace *ns,

#ifdef CONFIG_USER_NS

extern int unprivileged_userns_clone;

static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
{
if (ns)
Expand Down Expand Up @@ -192,6 +194,8 @@ extern bool current_in_userns(const struct user_namespace *target_ns);
struct ns_common *ns_get_owner(struct ns_common *ns);
#else

#define unprivileged_userns_clone 0

static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
{
return &init_user_ns;
Expand Down
16 changes: 16 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,22 @@ config USER_NS

If unsure, say N.

config USER_NS_UNPRIVILEGED
bool "Allow unprivileged users to create namespaces"
default y
depends on USER_NS
help
When disabled, unprivileged users will not be able to create
new namespaces. Allowing users to create their own namespaces
has been part of several recent local privilege escalation
exploits, so if you need user namespaces but are
paranoid^Wsecurity-conscious you want to disable this.

This setting can be overridden at runtime via the
kernel.unprivileged_userns_clone sysctl.

If unsure, say Y.

config PID_NS
bool "PID Namespaces"
default y
Expand Down
14 changes: 14 additions & 0 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
#include <linux/pidfs.h>
#include <linux/tick.h>

#ifdef CONFIG_USER_NS
#include <linux/user_namespace.h>
#endif

#include <asm/pgalloc.h>
#include <linux/uaccess.h>
#include <asm/mmu_context.h>
Expand Down Expand Up @@ -2138,6 +2142,10 @@ __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.
Expand Down Expand Up @@ -3291,6 +3299,12 @@ int ksys_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;
Expand Down
12 changes: 12 additions & 0 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
#ifdef CONFIG_RT_MUTEXES
#include <linux/rtmutex.h>
#endif
#ifdef CONFIG_USER_NS
#include <linux/user_namespace.h>
#endif

/* shared constants to be used in various sysctls */
const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100, 200, 1000, 3000, INT_MAX, 65535, -1 };
Expand Down Expand Up @@ -1618,6 +1621,15 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
#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",
Expand Down
7 changes: 7 additions & 0 deletions kernel/user_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
#include <linux/bsearch.h>
#include <linux/sort.h>

/* sysctl */
#ifdef CONFIG_USER_NS_UNPRIVILEGED
int unprivileged_userns_clone = 1;
#else
int unprivileged_userns_clone;
#endif

static struct kmem_cache *user_ns_cachep __ro_after_init;
static DEFINE_MUTEX(userns_state_mutex);

Expand Down

0 comments on commit a256060

Please sign in to comment.