userns: add sysctl to disallow unprivileged CLONE_NEWUSER by default
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com> [bwh: Remove unneeded binary sysctl bits] Signed-off-by: Daniel Micay <danielmicay@gmail.com> [thibaut.sautereau@ssi.gouv.fr: Adapt to sysctl code refactoring] Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr> Signed-off-by: Levente Polyak <levente@leventepolyak.net>
This commit is contained in:
parent
b8feef85e0
commit
8617bae36d
|
@ -148,6 +148,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)
|
||||
|
@ -181,6 +183,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;
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include <linux/perf_event.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/khugepaged.h>
|
||||
#include <linux/signalfd.h>
|
||||
|
@ -2022,6 +2023,10 @@ static __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.
|
||||
|
@ -3181,6 +3186,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;
|
||||
|
|
|
@ -81,6 +81,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 };
|
||||
|
@ -1659,6 +1662,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",
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include <linux/bsearch.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
/* sysctl */
|
||||
int unprivileged_userns_clone;
|
||||
|
||||
static struct kmem_cache *user_ns_cachep __read_mostly;
|
||||
static DEFINE_MUTEX(userns_state_mutex);
|
||||
|
||||
|
|
Loading…
Reference in a new issue