aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/pid_namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/pid_namespace.c')
-rw-r--r--kernel/pid_namespace.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index fab8ea86fac3..86b3796b0436 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -67,9 +67,10 @@ err_alloc:
67 return NULL; 67 return NULL;
68} 68}
69 69
70static struct pid_namespace *create_pid_namespace(unsigned int level) 70static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
71{ 71{
72 struct pid_namespace *ns; 72 struct pid_namespace *ns;
73 unsigned int level = parent_pid_ns->level + 1;
73 int i; 74 int i;
74 75
75 ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL); 76 ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
@@ -86,6 +87,7 @@ static struct pid_namespace *create_pid_namespace(unsigned int level)
86 87
87 kref_init(&ns->kref); 88 kref_init(&ns->kref);
88 ns->level = level; 89 ns->level = level;
90 ns->parent = get_pid_ns(parent_pid_ns);
89 91
90 set_bit(0, ns->pidmap[0].page); 92 set_bit(0, ns->pidmap[0].page);
91 atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1); 93 atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
@@ -114,25 +116,11 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
114 116
115struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns) 117struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
116{ 118{
117 struct pid_namespace *new_ns;
118
119 BUG_ON(!old_ns);
120 new_ns = get_pid_ns(old_ns);
121 if (!(flags & CLONE_NEWPID)) 119 if (!(flags & CLONE_NEWPID))
122 goto out; 120 return get_pid_ns(old_ns);
123 121 if (flags & (CLONE_THREAD|CLONE_PARENT))
124 new_ns = ERR_PTR(-EINVAL); 122 return ERR_PTR(-EINVAL);
125 if (flags & CLONE_THREAD) 123 return create_pid_namespace(old_ns);
126 goto out_put;
127
128 new_ns = create_pid_namespace(old_ns->level + 1);
129 if (!IS_ERR(new_ns))
130 new_ns->parent = get_pid_ns(old_ns);
131
132out_put:
133 put_pid_ns(old_ns);
134out:
135 return new_ns;
136} 124}
137 125
138void free_pid_ns(struct kref *kref) 126void free_pid_ns(struct kref *kref)
@@ -152,6 +140,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
152{ 140{
153 int nr; 141 int nr;
154 int rc; 142 int rc;
143 struct task_struct *task;
155 144
156 /* 145 /*
157 * The last thread in the cgroup-init thread group is terminating. 146 * The last thread in the cgroup-init thread group is terminating.
@@ -169,7 +158,19 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
169 read_lock(&tasklist_lock); 158 read_lock(&tasklist_lock);
170 nr = next_pidmap(pid_ns, 1); 159 nr = next_pidmap(pid_ns, 1);
171 while (nr > 0) { 160 while (nr > 0) {
172 kill_proc_info(SIGKILL, SEND_SIG_PRIV, nr); 161 rcu_read_lock();
162
163 /*
164 * Use force_sig() since it clears SIGNAL_UNKILLABLE ensuring
165 * any nested-container's init processes don't ignore the
166 * signal
167 */
168 task = pid_task(find_vpid(nr), PIDTYPE_PID);
169 if (task)
170 force_sig(SIGKILL, task);
171
172 rcu_read_unlock();
173
173 nr = next_pidmap(pid_ns, nr); 174 nr = next_pidmap(pid_ns, nr);
174 } 175 }
175 read_unlock(&tasklist_lock); 176 read_unlock(&tasklist_lock);