ZEN: Add sysctl and CONFIG to disallow unprivileged CLONE_NEWUSER
Our default behavior continues to match the vanilla kernel.
This commit is contained in:
parent
98f7e32f20
commit
dd778eae3f
5 changed files with 53 additions and 0 deletions
|
@ -156,6 +156,8 @@ static inline void set_userns_rlimit_max(struct user_namespace *ns,
|
||||||
|
|
||||||
#ifdef CONFIG_USER_NS
|
#ifdef CONFIG_USER_NS
|
||||||
|
|
||||||
|
extern int unprivileged_userns_clone;
|
||||||
|
|
||||||
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
||||||
{
|
{
|
||||||
if (ns)
|
if (ns)
|
||||||
|
@ -189,6 +191,8 @@ extern bool current_in_userns(const struct user_namespace *target_ns);
|
||||||
struct ns_common *ns_get_owner(struct ns_common *ns);
|
struct ns_common *ns_get_owner(struct ns_common *ns);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define unprivileged_userns_clone 0
|
||||||
|
|
||||||
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
||||||
{
|
{
|
||||||
return &init_user_ns;
|
return &init_user_ns;
|
||||||
|
|
16
init/Kconfig
16
init/Kconfig
|
@ -1265,6 +1265,22 @@ config USER_NS
|
||||||
|
|
||||||
If unsure, say N.
|
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
|
config PID_NS
|
||||||
bool "PID Namespaces"
|
bool "PID Namespaces"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -105,6 +105,10 @@
|
||||||
#include <uapi/linux/pidfd.h>
|
#include <uapi/linux/pidfd.h>
|
||||||
#include <linux/pidfs.h>
|
#include <linux/pidfs.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_NS
|
||||||
|
#include <linux/user_namespace.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
@ -2138,6 +2142,10 @@ __latent_entropy struct task_struct *copy_process(
|
||||||
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
|
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
|
||||||
return ERR_PTR(-EINVAL);
|
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
|
* Thread groups must share signals as well, and detached threads
|
||||||
* can only be started up within the thread group.
|
* can only be started up within the thread group.
|
||||||
|
@ -3287,6 +3295,12 @@ int ksys_unshare(unsigned long unshare_flags)
|
||||||
if (unshare_flags & CLONE_NEWNS)
|
if (unshare_flags & CLONE_NEWNS)
|
||||||
unshare_flags |= CLONE_FS;
|
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);
|
err = check_unshare_flags(unshare_flags);
|
||||||
if (err)
|
if (err)
|
||||||
goto bad_unshare_out;
|
goto bad_unshare_out;
|
||||||
|
|
|
@ -80,6 +80,9 @@
|
||||||
#ifdef CONFIG_RT_MUTEXES
|
#ifdef CONFIG_RT_MUTEXES
|
||||||
#include <linux/rtmutex.h>
|
#include <linux/rtmutex.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_USER_NS
|
||||||
|
#include <linux/user_namespace.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* shared constants to be used in various sysctls */
|
/* 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 };
|
const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100, 200, 1000, 3000, INT_MAX, 65535, -1 };
|
||||||
|
@ -1618,6 +1621,15 @@ static struct ctl_table kern_table[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec,
|
.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
|
#ifdef CONFIG_PROC_SYSCTL
|
||||||
{
|
{
|
||||||
.procname = "tainted",
|
.procname = "tainted",
|
||||||
|
|
|
@ -22,6 +22,13 @@
|
||||||
#include <linux/bsearch.h>
|
#include <linux/bsearch.h>
|
||||||
#include <linux/sort.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 struct kmem_cache *user_ns_cachep __ro_after_init;
|
||||||
static DEFINE_MUTEX(userns_state_mutex);
|
static DEFINE_MUTEX(userns_state_mutex);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue