diff options
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 478bad2745e..7b07cc0dfb7 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)  {  | 
