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:
Serge Hallyn 2013-05-31 19:12:12 +01:00 committed by Levente Polyak
parent b8feef85e0
commit 8617bae36d
No known key found for this signature in database
GPG key ID: FC1B547C8D8172C8
4 changed files with 30 additions and 0 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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",

View file

@ -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);