diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-17 05:48:13 +0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-17 05:49:06 +0400 |
commit | 85910c202bb869edd2bb9a6c217a658c83f06f1e (patch) | |
tree | fcf4bf1ba2ebfcb6dec395a10ed6b33e7d33217e /kernel/pid_namespace.c | |
parent | f7200d4c504a385b1b70f3bab379f99745f7ef6a (diff) | |
parent | 517ffce4e1a03aea979fe3a18a3dd1761a24fafb (diff) | |
download | linux-85910c202bb869edd2bb9a6c217a658c83f06f1e.tar.xz |
Merge commit '517ffce4e1a03aea979fe3a18a3dd1761a24fafb' into arch-sparc
Backmerge from the point in mainline where a trivial conflict had been
introduced (arch/sparc/kernel/sys_sparc_64.c had grown sys_kern_features()
right after where kernel_execve() used to be)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/pid_namespace.c')
-rw-r--r-- | kernel/pid_namespace.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 478bad2745e3..7b07cc0dfb75 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -71,12 +71,22 @@ err_alloc: return NULL; } +/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */ +#define MAX_PID_NS_LEVEL 32 + static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns) { struct pid_namespace *ns; unsigned int level = parent_pid_ns->level + 1; - int i, err = -ENOMEM; + int i; + int err; + + if (level > MAX_PID_NS_LEVEL) { + err = -EINVAL; + goto out; + } + err = -ENOMEM; ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL); if (ns == NULL) goto out; @@ -133,19 +143,26 @@ struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old return create_pid_namespace(old_ns); } -void free_pid_ns(struct kref *kref) +static void free_pid_ns(struct kref *kref) { - struct pid_namespace *ns, *parent; + struct pid_namespace *ns; ns = container_of(kref, struct pid_namespace, kref); - - parent = ns->parent; destroy_pid_namespace(ns); +} + +void put_pid_ns(struct pid_namespace *ns) +{ + struct pid_namespace *parent; - if (parent != NULL) - put_pid_ns(parent); + while (ns != &init_pid_ns) { + parent = ns->parent; + if (!kref_put(&ns->kref, free_pid_ns)) + break; + ns = parent; + } } -EXPORT_SYMBOL_GPL(free_pid_ns); +EXPORT_SYMBOL_GPL(put_pid_ns); void zap_pid_ns_processes(struct pid_namespace *pid_ns) { |