Prev: linux-next: build failure after merge of the final tree (block tree related)
Next: [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path
From: Eric W. Biederman on 9 Jul 2010 00:40 Currently we have some subtle races when a pid namespace exits and we need a simple way of close those races. To close those races in a simple way I introduce an atomic flag PIDNS_DEAD that we can teest to see if a pid namespace has died. When PIDNS_DEAD is set for a pid namespace all attempts to lookup or add a pid to the pid namespace will fail. Signed-off-by: Eric W. Biederman <ebiederm(a)xmission.com> --- include/linux/pid_namespace.h | 7 +++++++ kernel/fork.c | 3 ++- kernel/pid.c | 7 +++++++ kernel/pid_namespace.c | 1 + 4 files changed, 17 insertions(+), 1 deletions(-) diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 38d1032..dcee0b3 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -16,10 +16,17 @@ struct pidmap { struct bsd_acct_struct; +enum pidns_flags { + PIDNS_DEAD, /* When set do not allow lookups of pids in the pid namespace, + * or adding new pids to the pid namespace. + */ +}; + struct pid_namespace { struct kref kref; struct pidmap pidmap[PIDMAP_ENTRIES]; int last_pid; + unsigned long flags; struct task_struct *child_reaper; struct kmem_cache *pid_cachep; unsigned int level; diff --git a/kernel/fork.c b/kernel/fork.c index f36585c..9818b20 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1237,7 +1237,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, * thread can't slip out of an OOM kill (or normal SIGKILL). */ recalc_sigpending(); - if (signal_pending(current)) { + if (signal_pending(current) || + test_bit(PIDNS_DEAD, &p->nsproxy->pid_ns->flags)) { spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); retval = -ERESTARTNOINTR; diff --git a/kernel/pid.c b/kernel/pid.c index e9fd8c1..1a921c7 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -248,6 +248,10 @@ struct pid *alloc_pid(struct pid_namespace *ns) struct pid_namespace *tmp; struct upid *upid; + pid = NULL; + if (test_bit(PIDNS_DEAD, &ns->flags)) + goto out; + pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) goto out; @@ -293,6 +297,9 @@ struct pid *find_pid_ns(int nr, struct pid_namespace *ns) struct hlist_node *elem; struct upid *pnr; + if (test_bit(PIDNS_DEAD, &ns->flags)) + return NULL; + hlist_for_each_entry_rcu(pnr, elem, &pid_hash[pid_hashfn(nr, ns)], pid_chain) if (pnr->nr == nr && pnr->ns == ns) diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index cf8a562..92032d1 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -181,6 +181,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) nr = next_pidmap(pid_ns, nr); } + set_bit(PIDNS_DEAD, &pid_ns->flags); read_unlock(&tasklist_lock); do { -- 1.6.5.2.143.g8cc62 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |