kernel/taskstats.c | 16 ++++++++++++++-- 1 files changed, 14 insertions(+), 2 deletions(-) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index fc0f22005417..620e89ae96cf 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,7 @@ static const struct nla_policy cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_M struct listener { struct list_head list; pid_t pid; + struct pid_namespace *pid_ns; char valid; }; @@ -127,6 +129,7 @@ static int send_reply(struct sk_buff *skb, struct genl_info *info) static void send_cpu_listeners(struct sk_buff *skb, struct listener_list *listeners) { + struct pid_namespace *current_ns; struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb)); struct listener *s, *tmp; struct sk_buff *skb_next, *skb_cur = skb; @@ -140,8 +143,15 @@ static void send_cpu_listeners(struct sk_buff *skb, } rc = 0; + current_ns = task_active_pid_ns(current); down_read(&listeners->sem); list_for_each_entry(s, &listeners->list, list) { + /* + * BROKEN: what if "s" is stale? This way it will + * never be marked invalid! + */ + if (s->pid_ns != current_ns) + continue; skb_next = NULL; if (!list_is_last(&s->list, &listeners->list)) { skb_next = skb_clone(skb_cur, GFP_KERNEL); @@ -287,6 +297,7 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) struct listener_list *listeners; struct listener *s, *tmp, *s2; unsigned int cpu; + struct pid_namespace *pid_ns = task_active_pid_ns(current); if (!cpumask_subset(mask, cpu_possible_mask)) return -EINVAL; @@ -300,13 +311,14 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) if (!s) goto cleanup; s->pid = pid; + s->pid_ns = pid_ns; INIT_LIST_HEAD(&s->list); s->valid = 1; listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); list_for_each_entry_safe(s2, tmp, &listeners->list, list) { - if (s2->pid == pid) + if (s2->pid == pid && s2->pid_ns == pid_ns) goto next_cpu; } list_add(&s->list, &listeners->list); @@ -324,7 +336,7 @@ cleanup: listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); list_for_each_entry_safe(s, tmp, &listeners->list, list) { - if (s->pid == pid) { + if (s->pid == pid && s->pid_ns == pid_ns) { list_del(&s->list); kfree(s); break;