From: Shailabh Nagar Use a cloned sk_buff for each netlink message sent to multiple listeners. Earlier, the same skb, representing a netlink message, was being erroneously reused for doing genetlink_unicast()'s (effectively netlink_unicast()) to each listener on the per-cpu list of listeners. Since netlink_unicast() frees up the skb passed to it, regardless of status of the send, reuse is bad. Thanks to Chandra Seetharaman for discovering this bug. Signed-off-by: Shailabh Nagar Signed-off-by: Chandra Seetharaman Signed-off-by: Andrew Morton --- kernel/taskstats.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff -puN kernel/taskstats.c~per-task-delay-accounting-taskstats-interface-control-exit-data-through-cpumasks-fix-cleanup-fix kernel/taskstats.c --- a/kernel/taskstats.c~per-task-delay-accounting-taskstats-interface-control-exit-data-through-cpumasks-fix-cleanup-fix +++ a/kernel/taskstats.c @@ -125,6 +125,7 @@ static int send_cpu_listeners(struct sk_ struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); struct listener_list *listeners; struct listener *s, *tmp; + struct sk_buff *skb_next, *skb_cur = skb; void *reply = genlmsg_data(genlhdr); int rc, ret; @@ -138,12 +139,22 @@ static int send_cpu_listeners(struct sk_ listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); list_for_each_entry_safe(s, tmp, &listeners->list, list) { - ret = genlmsg_unicast(skb, s->pid); + skb_next = NULL; + if (!list_islast(&s->list, &listeners->list)) { + skb_next = skb_clone(skb_cur, GFP_KERNEL); + if (!skb_next) { + nlmsg_free(skb_cur); + rc = -ENOMEM; + break; + } + } + ret = genlmsg_unicast(skb_cur, s->pid); if (ret == -ECONNREFUSED) { list_del(&s->list); kfree(s); rc = ret; } + skb_cur = skb_next; } up_write(&listeners->sem); _