summaryrefslogtreecommitdiff
path: root/kernel/pid_namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-11-17 05:48:13 +0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-11-17 05:49:06 +0400
commit85910c202bb869edd2bb9a6c217a658c83f06f1e (patch)
treefcf4bf1ba2ebfcb6dec395a10ed6b33e7d33217e /kernel/pid_namespace.c
parentf7200d4c504a385b1b70f3bab379f99745f7ef6a (diff)
parent517ffce4e1a03aea979fe3a18a3dd1761a24fafb (diff)
downloadlinux-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.c33
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)
{