diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2016-07-30 20:58:49 +0200 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2016-08-08 20:18:58 +0200 |
commit | dbec28460a89aa7c02c3301e9e108d98272549d2 (patch) | |
tree | bf4b71c69e072bb6fdbe680674ab84bd79143e45 /kernel/user_namespace.c | |
parent | userns: Free user namespaces in process context (diff) | |
download | linux-dbec28460a89aa7c02c3301e9e108d98272549d2.tar.xz linux-dbec28460a89aa7c02c3301e9e108d98272549d2.zip |
userns: Add per user namespace sysctls.
Limit per userns sysctls to only be opened for write by a holder
of CAP_SYS_RESOURCE.
Add all of the necessary boilerplate for having per user namespace
sysctls.
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r-- | kernel/user_namespace.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 5247cdb24e62..a63332253c7e 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -23,6 +23,9 @@ #include <linux/projid.h> #include <linux/fs_struct.h> +extern bool setup_userns_sysctls(struct user_namespace *ns); +extern void retire_userns_sysctls(struct user_namespace *ns); + static struct kmem_cache *user_ns_cachep __read_mostly; static DEFINE_MUTEX(userns_state_mutex); @@ -109,12 +112,22 @@ int create_user_ns(struct cred *new) ns->flags = parent_ns->flags; mutex_unlock(&userns_state_mutex); - set_cred_user_ns(new, ns); - #ifdef CONFIG_PERSISTENT_KEYRINGS init_rwsem(&ns->persistent_keyring_register_sem); #endif + ret = -ENOMEM; + if (!setup_userns_sysctls(ns)) + goto fail_keyring; + + set_cred_user_ns(new, ns); return 0; +fail_keyring: +#ifdef CONFIG_PERSISTENT_KEYRINGS + key_put(ns->persistent_keyring_register); +#endif + ns_free_inum(&ns->ns); + kmem_cache_free(user_ns_cachep, ns); + return ret; } int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) @@ -144,6 +157,7 @@ static void free_user_ns(struct work_struct *work) do { parent = ns->parent; + retire_userns_sysctls(ns); #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); #endif |