From bbc2e3ef87851bc5430b2b4cf4ca3a2f29baeda6 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 19 Oct 2012 13:56:53 -0700 Subject: pidns: remove recursion from free_pid_ns() free_pid_ns() operates in a recursive fashion: free_pid_ns(parent) put_pid_ns(parent) kref_put(&ns->kref, free_pid_ns); free_pid_ns thus if there was a huge nesting of namespaces the userspace may trigger avalanche calling of free_pid_ns leading to kernel stack exhausting and a panic eventually. This patch turns the recursion into an iterative loop. Based on a patch by Andrew Vagin. [akpm@linux-foundation.org: export put_pid_ns() to modules] Signed-off-by: Cyrill Gorcunov Cc: Andrew Vagin Cc: Oleg Nesterov Cc: "Eric W. Biederman" Cc: Pavel Emelyanov Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/pid_namespace.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'kernel/pid_namespace.c') diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 478bad2745e3..eb00be205811 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -133,19 +133,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); +} - if (parent != NULL) - put_pid_ns(parent); +void put_pid_ns(struct pid_namespace *ns) +{ + struct pid_namespace *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) { -- cgit v1.2.3