diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2010-07-12 21:50:25 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-11-19 08:59:11 -0500 |
commit | 5e1182deb81ae8c68494017c4a8a71811659c870 (patch) | |
tree | 81b9fa941a3293f6d5fa4e32aa311988bb3bf985 /kernel | |
parent | 0a01f2cc390e10633a54f72c608cc3fe19a50c3d (diff) |
pidns: Don't allow new processes in a dead pid namespace.
Set nr_hashed to -1 just before we schedule the work to cleanup proc.
Test nr_hashed just before we hash a new pid and if nr_hashed is < 0
fail.
This guaranteees that processes never enter a pid namespaces after we
have cleaned up the state to support processes in a pid namespace.
Currently sending SIGKILL to all of the process in a pid namespace as
init exists gives us this guarantee but we need something a little
stronger to support unsharing and joining a pid namespace.
Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/pid.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/kernel/pid.c b/kernel/pid.c index e957f8b09136..9c219117af36 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -274,8 +274,10 @@ void free_pid(struct pid *pid) | |||
274 | for (i = 0; i <= pid->level; i++) { | 274 | for (i = 0; i <= pid->level; i++) { |
275 | struct upid *upid = pid->numbers + i; | 275 | struct upid *upid = pid->numbers + i; |
276 | hlist_del_rcu(&upid->pid_chain); | 276 | hlist_del_rcu(&upid->pid_chain); |
277 | if (--upid->ns->nr_hashed == 0) | 277 | if (--upid->ns->nr_hashed == 0) { |
278 | upid->ns->nr_hashed = -1; | ||
278 | schedule_work(&upid->ns->proc_work); | 279 | schedule_work(&upid->ns->proc_work); |
280 | } | ||
279 | } | 281 | } |
280 | spin_unlock_irqrestore(&pidmap_lock, flags); | 282 | spin_unlock_irqrestore(&pidmap_lock, flags); |
281 | 283 | ||
@@ -321,6 +323,8 @@ struct pid *alloc_pid(struct pid_namespace *ns) | |||
321 | 323 | ||
322 | upid = pid->numbers + ns->level; | 324 | upid = pid->numbers + ns->level; |
323 | spin_lock_irq(&pidmap_lock); | 325 | spin_lock_irq(&pidmap_lock); |
326 | if (ns->nr_hashed < 0) | ||
327 | goto out_unlock; | ||
324 | for ( ; upid >= pid->numbers; --upid) { | 328 | for ( ; upid >= pid->numbers; --upid) { |
325 | hlist_add_head_rcu(&upid->pid_chain, | 329 | hlist_add_head_rcu(&upid->pid_chain, |
326 | &pid_hash[pid_hashfn(upid->nr, upid->ns)]); | 330 | &pid_hash[pid_hashfn(upid->nr, upid->ns)]); |
@@ -331,6 +335,8 @@ struct pid *alloc_pid(struct pid_namespace *ns) | |||
331 | out: | 335 | out: |
332 | return pid; | 336 | return pid; |
333 | 337 | ||
338 | out_unlock: | ||
339 | spin_unlock(&pidmap_lock); | ||
334 | out_free: | 340 | out_free: |
335 | while (++i <= ns->level) | 341 | while (++i <= ns->level) |
336 | free_pidmap(pid->numbers + i); | 342 | free_pidmap(pid->numbers + i); |