diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2016-08-08 14:25:30 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2016-08-08 14:42:03 -0500 |
commit | d08311dd6fd8444e39710dd2fb97562895aed8fa (patch) | |
tree | cc695dce4603db22fe5bb0789467ae4d9481f084 /kernel | |
parent | aba356616386e6e573a34c6d64ed12443686e5c8 (diff) |
cgroupns: Add a limit on the number of cgroup namespaces
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup.c | 18 | ||||
-rw-r--r-- | kernel/ucount.c | 1 |
2 files changed, 19 insertions, 0 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index d1c51b7f5221..e9e4427fec46 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -6295,6 +6295,16 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd) /* cgroup namespaces */ +static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns) +{ + return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES); +} + +static void dec_cgroup_namespaces(struct ucounts *ucounts) +{ + dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES); +} + static struct cgroup_namespace *alloc_cgroup_ns(void) { struct cgroup_namespace *new_ns; @@ -6316,6 +6326,7 @@ static struct cgroup_namespace *alloc_cgroup_ns(void) void free_cgroup_ns(struct cgroup_namespace *ns) { put_css_set(ns->root_cset); + dec_cgroup_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); kfree(ns); @@ -6327,6 +6338,7 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, struct cgroup_namespace *old_ns) { struct cgroup_namespace *new_ns; + struct ucounts *ucounts; struct css_set *cset; BUG_ON(!old_ns); @@ -6340,6 +6352,10 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, if (!ns_capable(user_ns, CAP_SYS_ADMIN)) return ERR_PTR(-EPERM); + ucounts = inc_cgroup_namespaces(user_ns); + if (!ucounts) + return ERR_PTR(-ENFILE); + /* It is not safe to take cgroup_mutex here */ spin_lock_irq(&css_set_lock); cset = task_css_set(current); @@ -6349,10 +6365,12 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, new_ns = alloc_cgroup_ns(); if (IS_ERR(new_ns)) { put_css_set(cset); + dec_cgroup_namespaces(ucounts); return new_ns; } new_ns->user_ns = get_user_ns(user_ns); + new_ns->ucounts = ucounts; new_ns->root_cset = cset; return new_ns; diff --git a/kernel/ucount.c b/kernel/ucount.c index fbab75424da6..335cc5d2cdd7 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -71,6 +71,7 @@ static struct ctl_table user_table[] = { UCOUNT_ENTRY("max_pid_namespaces"), UCOUNT_ENTRY("max_uts_namespaces"), UCOUNT_ENTRY("max_ipc_namespaces"), + UCOUNT_ENTRY("max_cgroup_namespaces"), { } }; #endif /* CONFIG_SYSCTL */ |