netlink: Fix dump skb leak/double free
Herbert Xu [Mon, 16 May 2016 09:28:16 +0000 (17:28 +0800)]
When we free cb->skb after a dump, we do it after releasing the
lock.  This means that a new dump could have started in the time
being and we'll end up freeing their skb instead of ours.

This patch saves the skb and module before we unlock so we free
the right memory.

Bug 1880704

Change-Id: I99a013d97bbbb793ebc0a196cd0e35ec198e3cb1
Fixes: 16b304f3404f ("netlink: Eliminate kmalloc in netlink dump operation.")
Reported-by: Baozeng Ding <sploving1@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Gagan Grover <ggrover@nvidia.com>
Reviewed-on: http://git-master/r/1311849
(cherry picked from commit 2605cb0c4277297fdcab1257f796d623f649235f)
Reviewed-on: http://git-master/r/1330547
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>

net/netlink/af_netlink.c

index f30c1a2..1599f0e 100644 (file)
@@ -707,7 +707,6 @@ static void netlink_destroy_callback(struct netlink_callback *cb)
 
 static void netlink_consume_callback(struct netlink_callback *cb)
 {
-       consume_skb(cb->skb);
        kfree(cb);
 }
 
@@ -2474,6 +2473,7 @@ static int netlink_dump(struct sock *sk)
        struct netlink_callback *cb;
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
+       struct module *module;
        int len, err = -ENOBUFS;
        int alloc_size;
 
@@ -2523,10 +2523,14 @@ static int netlink_dump(struct sock *sk)
        if (cb->done)
                cb->done(cb);
        nlk->cb = NULL;
+       module = cb->module;
+       skb = cb->skb;
        mutex_unlock(nlk->cb_mutex);
 
-       module_put(cb->module);
+       module_put(module);
+       consume_skb(skb);
        netlink_consume_callback(cb);
+
        return 0;
 
 errout_skb: