BUG: use-after-free in netlink_dump
Subsystems (2)
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+.
==================================================================
BUG: KASAN: use-after-free in netlink_dump+0x4eb/0xa40 at addr ffff880036ae7988 Read of size 4 by task syz-executor/14596 =============================================================================
BUG kmalloc-1024 (Tainted: G B ): kasan: bad access detected
-----------------------------------------------------------------------------
INFO: Allocated in 0xbbbbbbbbbbbbbbbb age=18446681375777959590 cpu=0 pid=0
[< none >] __alloc_skb+0xf0/0x5f0 net/core/skbuff.c:230 [< none >] ___slab_alloc+0x4c7/0x500 mm/slub.c:2446 [< none >] __slab_alloc+0x4c/0x90 mm/slub.c:2475 [< inline >] slab_alloc_node mm/slub.c:2538 [< none >] __kmalloc_node_track_caller+0xba/0x420 mm/slub.c:4095 [< none >] __kmalloc_reserve.isra.33+0x41/0xe0 net/core/skbuff.c:137 [< none >] __alloc_skb+0xf0/0x5f0 net/core/skbuff.c:230 [< inline >] alloc_skb include/linux/skbuff.h:895 [< inline >] netlink_alloc_large_skb net/netlink/af_netlink.c:1086 [< none >] netlink_sendmsg+0x8cd/0xcb0 net/netlink/af_netlink.c:1761 [< inline >] sock_sendmsg_nosec net/socket.c:612 [< none >] sock_sendmsg+0xca/0x110 net/socket.c:622 [< none >] ___sys_sendmsg+0x728/0x860 net/socket.c:1946 [< none >] __sys_sendmsg+0xd1/0x170 net/socket.c:1980 [< inline >] SYSC_sendmsg net/socket.c:1991 [< none >] SyS_sendmsg+0x2d/0x50 net/socket.c:1987 [< none >] entry_SYSCALL_64_fastpath+0x23/0xc1 arch/x86/entry/entry_64.S:207 INFO: Freed in 0x1000f2d5f age=18446681375777959590 cpu=0 pid=0 [< inline >] skb_free_head net/core/skbuff.c:579 [< none >] skb_release_data+0x361/0x430 net/core/skbuff.c:610 [< none >] __slab_free+0x1e8/0x300 mm/slub.c:2657 [< inline >] slab_free mm/slub.c:2810 [< none >] kfree+0x255/0x2d0 mm/slub.c:3661 [< inline >] skb_free_head net/core/skbuff.c:579 [< none >] skb_release_data+0x361/0x430 net/core/skbuff.c:610 [< none >] skb_release_all+0x4a/0x60 net/core/skbuff.c:669 [< inline >] __kfree_skb net/core/skbuff.c:683 [< none >] consume_skb+0x11b/0x2f0 net/core/skbuff.c:756 [< inline >] netlink_unicast_kernel net/netlink/af_netlink.c:1215 [< none >] netlink_unicast+0x5aa/0x890 net/netlink/af_netlink.c:1240 [< none >] netlink_sendmsg+0x981/0xcb0 net/netlink/af_netlink.c:1786 [< inline >] sock_sendmsg_nosec net/socket.c:612 [< none >] sock_sendmsg+0xca/0x110 net/socket.c:622 [< none >] ___sys_sendmsg+0x728/0x860 net/socket.c:1946 [< none >] __sys_sendmsg+0xd1/0x170 net/socket.c:1980 [< inline >] SYSC_sendmsg net/socket.c:1991 [< none >] SyS_sendmsg+0x2d/0x50 net/socket.c:1987 [< none >] entry_SYSCALL_64_fastpath+0x23/0xc1 arch/x86/entry/entry_64.S:207 INFO: Slab 0xffffea0000dab800 objects=24 used=8 fp=0xffff880036ae7980 flags=0x1fffc0000004080 INFO: Object 0xffff880036ae7978 @offset=31096 fp=0xbbbbbbbbbbbbbbbb CPU: 0 PID: 14596 Comm: syz-executor Tainted: G B 4.6.0-rc2+ #16 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/0xa40net/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/0xe00net/netlink/af_netlink.c:1869
[<ffffffff84cdc8a0>] ? netlink_dump+0xa40/0xa40include/linux/skbuff.h:1980
[<ffffffff81768c23>] ? rw_copy_check_uvector+0x1c3/0x260fs/read_write.c:818
[<ffffffff829953b6>] ? import_iovec+0x216/0x3c0 lib/iov_iter.c:811 [<ffffffff829951a0>] ? iov_iter_get_pages_alloc+0x960/0x960lib/iov_iter.c:629
[<ffffffff82696ecf>] ? security_socket_recvmsg+0x8f/0xc0security/security.c:1244
[< inline >] sock_recvmsg_nosec net/socket.c:714
[<ffffffff84b3797d>] sock_recvmsg+0x9d/0xb0 net/socket.c:722
[<ffffffff84b378e0>] ? __sock_recv_wifi_status+0x180/0x180
./arch/x86/include/asm/bitops.h:311
[<ffffffff84b3a769>] ___sys_recvmsg+0x259/0x540 net/socket.c:2104
[< inline >] ? sock_sendmsg_nosec net/socket.c:612
[<ffffffff84b3a510>] ? ___sys_sendmsg+0x860/0x860 net/socket.c:1943
[< inline >] ? rcu_read_unlock include/linux/rcupdate.h:922
[<ffffffff817c165c>] ? __fget+0x20c/0x3b0 fs/file.c:712
[< inline >] ? rcu_lock_release include/linux/rcupdate.h:491
[< inline >] ? rcu_read_unlock include/linux/rcupdate.h:926
[<ffffffff817c1685>] ? __fget+0x235/0x3b0 fs/file.c:712
[<ffffffff817c1497>] ? __fget+0x47/0x3b0 fs/file.c:696
[<ffffffff817c18e1>] ? __fget_light+0xa1/0x1f0 fs/file.c:759
[<ffffffff817c1a48>] ? __fdget+0x18/0x20 fs/file.c:764
[<ffffffff84b360c8>] ? sockfd_lookup_light+0xf8/0x1f0 net/socket.c:463
[<ffffffff84b3c95e>] __sys_recvmsg+0xce/0x170 net/socket.c:2150
[<ffffffff84b3c890>] ? SyS_sendmmsg+0x60/0x60 net/socket.c:2064
[< inline >] SYSC_recvmsg net/socket.c:2162
[<ffffffff84b3ca2d>] SyS_recvmsg+0x2d/0x50 net/socket.c:2157
[<ffffffff85c8ab80>] entry_SYSCALL_64_fastpath+0x23/0xc1
arch/x86/entry/entry_64.S:207
Memory state around the buggy address:
ffff880036ae7880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff880036ae7900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff880036ae7980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff880036ae7a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff880036ae7a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================Best Regards,
Baozeng Ding
Quoted 4 lines · Baozeng Ding
Hi all,
I've got the following report (use-after-free innetlink_dump) while running syzkaller.
Unfortunately no reproducer.The kernel version is 4.6.0-rc2+.
...
Quoted 9 lines
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
Quoted 8 lines
mm/kasan/report.c:317
[< inline >] ?nlmsg_put_answerinclude/net/netlink.h:471
[<ffffffff84cdc34b>] ?netlink_dump+0x4eb/0xa40net/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():
net/netlink/af_netlink.c +0 -0
@@ -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;
meanwhile the cb->skb is still "freed" by the consume_skb(cb->skb).
Quoted 6 lines · Cong Wang
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, thecb->skbis freed by one thread at the end ofnetlink_dump()meanwhile the other thread is still using it via NETLINK_CB(cb->skb).portid.
You're on the right track. I think what's happening is that the second thread is starting a new dump and the first thread ends up freeing the skb of the new dump and leaking the old skb.
---8<---
Subject: netlink: Fix dump skb leak/double free
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.
net/netlink/af_netlink.c +5 -2
@@ -2059,6 +2059,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_min_size;int alloc_size;
@@ -2134,9 +2135,11 @@ static int netlink_dump(struct sock *sk) cb->done (cb); nlk->cb_running = false; + module = cb->module; + skb = cb->skb;mutex_unlock (nlk->cb_mutex); -module_put (cb->module); -consume_skb (cb->skb); +module_put (module); +consume_skb (skb);return 0 ; errout_skb:
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Cong Wang
Acked-byQuoted 15 lines · Herbert Xu
Quoted 6 lines · Cong Wang
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, thecb->skbis freed by one thread at the end ofnetlink_dump()meanwhile the other thread is still using it via NETLINK_CB(cb->skb).portid.You're on the right track. I think what's happening is that the second thread is starting a new dump and the first thread ends up freeing the skb of the new dump and leaking the old skb.
---8<---
Subject: netlink: Fix dump skb leak/double free
Quoted 6 lines
When we free
cb->skbafter 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.
Yeah, this fix makes more sense than mine.
Quoted 4 lines
Fixes 16b304f3404f ("netlink: Eliminate kmalloc in netlink dump operation.")Reported-by Baozeng Ding <[email protected]>Signed-off-by Herbert Xu <[email protected]>
Thanks.
David Miller
maintainerFrom: Herbert Xu <[email protected]>
Date: Mon, 16 May 2016 17:28:16 +0800
Quoted 6 lines
Subject: netlink: Fix dump skb leak/double free
When we free
cb->skbafter 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.
Quoted 6 lines
This patch saves the skb and module before we unlock so we free the right memory.
Fixes 16b304f3404f ("netlink: Eliminate kmalloc in netlink dump operation.")Reported-by Baozeng Ding <[email protected]>Signed-off-by Herbert Xu <[email protected]>
Applied and queued up for -stable, thanks.