diff mbox

BUG: use-after-free in netlink_dump

Message ID CAM_iQpV90MKyP2X32yatwktO9Yk-CSb32Oaa+VpdU8e_k8m-yQ@mail.gmail.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Cong Wang May 15, 2016, 7:06 p.m. UTC
On Sun, May 15, 2016 at 8:24 AM, Baozeng Ding <sploving1@gmail.com> wrote:
> Hi all,
> I've got the following report (use-after-free in netlink_dump) while running
> syzkaller.
> Unfortunately no reproducer.The kernel version is 4.6.0-rc2+.
...
> Call Trace:
>  [<     inline     >] __dump_stack lib/dump_stack.c:15
>  [<ffffffff829557d1>] dump_stack+0xb3/0x112 lib/dump_stack.c:51
>  [<ffffffff8170fabd>] print_trailer+0x10d/0x190 mm/slub.c:667
>  [<ffffffff817165af>] object_err+0x2f/0x40 mm/slub.c:674
>  [<     inline     >] print_address_description mm/kasan/report.c:179
>  [<ffffffff81718dd8>] kasan_report_error+0x218/0x530 mm/kasan/report.c:275
>  [<     inline     >] kasan_report mm/kasan/report.c:297
>  [<ffffffff817191ae>] __asan_report_load4_noabort+0x3e/0x40
> mm/kasan/report.c:317
>  [<     inline     >] ? nlmsg_put_answer include/net/netlink.h:471
>  [<ffffffff84cdc34b>] ? netlink_dump+0x4eb/0xa40
> net/netlink/af_netlink.c:2120
>  [<     inline     >] nlmsg_put_answer include/net/netlink.h:471
>  [<ffffffff84cdc34b>] netlink_dump+0x4eb/0xa40 net/netlink/af_netlink.c:2120
>  [<ffffffff84cdd19b>] netlink_recvmsg+0x8fb/0xe00
> net/netlink/af_netlink.c:1869

Similar to what Richard reported, I think the problem is cb->skb,
which is exposed to other thread since cb is per netlink socket
(cb = &nlk->cb). IOW, the cb->skb is freed by one thread at the
end of netlink_dump() meanwhile the other thread is still using
it via NETLINK_CB(cb->skb).portid.

I am guessing we miss some skb_get():


meanwhile the cb->skb is still "freed" by the consume_skb(cb->skb).
diff mbox

Patch

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index aeefe12..142bb39 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2184,7 +2184,7 @@  int __netlink_dump_start(struct sock *ssk,
struct sk_buff *skb,
        cb->data = control->data;
        cb->module = control->module;
        cb->min_dump_alloc = control->min_dump_alloc;
-       cb->skb = skb;
+       cb->skb = skb_get(skb);

        nlk->cb_running = true;