diff options
author | Eric Dumazet <edumazet@google.com> | 2018-06-21 14:16:02 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-07-22 14:27:38 +0200 |
commit | 9dc96f7205d4bc8c99187c29dcdca5d31d6e7383 (patch) | |
tree | 9eed2310c60e3d1379acf734664c9d8e6f4115ae /net/packet | |
parent | e11eb6a3f96e7c05450a8bbc908bce0c9c13c77e (diff) |
net/packet: fix use-after-free
[ Upstream commit 945d015ee0c3095d2290e845565a23dedfd8027c ]
We should put copy_skb in receive_queue only after
a successful call to virtio_net_hdr_from_skb().
syzbot report :
BUG: KASAN: use-after-free in __skb_unlink include/linux/skbuff.h:1843 [inline]
BUG: KASAN: use-after-free in __skb_dequeue include/linux/skbuff.h:1863 [inline]
BUG: KASAN: use-after-free in skb_dequeue+0x16a/0x180 net/core/skbuff.c:2815
Read of size 8 at addr ffff8801b044ecc0 by task syz-executor217/4553
CPU: 0 PID: 4553 Comm: syz-executor217 Not tainted 4.18.0-rc1+ #111
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1c9/0x2b4 lib/dump_stack.c:113
print_address_description+0x6c/0x20b mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412
__asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433
__skb_unlink include/linux/skbuff.h:1843 [inline]
__skb_dequeue include/linux/skbuff.h:1863 [inline]
skb_dequeue+0x16a/0x180 net/core/skbuff.c:2815
skb_queue_purge+0x26/0x40 net/core/skbuff.c:2852
packet_set_ring+0x675/0x1da0 net/packet/af_packet.c:4331
packet_release+0x630/0xd90 net/packet/af_packet.c:2991
__sock_release+0xd7/0x260 net/socket.c:603
sock_close+0x19/0x20 net/socket.c:1186
__fput+0x35b/0x8b0 fs/file_table.c:209
____fput+0x15/0x20 fs/file_table.c:243
task_work_run+0x1ec/0x2a0 kernel/task_work.c:113
exit_task_work include/linux/task_work.h:22 [inline]
do_exit+0x1b08/0x2750 kernel/exit.c:865
do_group_exit+0x177/0x440 kernel/exit.c:968
__do_sys_exit_group kernel/exit.c:979 [inline]
__se_sys_exit_group kernel/exit.c:977 [inline]
__x64_sys_exit_group+0x3e/0x50 kernel/exit.c:977
do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x4448e9
Code: Bad RIP value.
RSP: 002b:00007ffd5f777ca8 EFLAGS: 00000202 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00000000004448e9
RDX: 00000000004448e9 RSI: 000000000000fcfb RDI: 0000000000000001
RBP: 00000000006cf018 R08: 00007ffd0000a45b R09: 0000000000000000
R10: 00007ffd5f777e48 R11: 0000000000000202 R12: 00000000004021f0
R13: 0000000000402280 R14: 0000000000000000 R15: 0000000000000000
Allocated by task 4553:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xc4/0xe0 mm/kasan/kasan.c:553
kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490
kmem_cache_alloc+0x12e/0x760 mm/slab.c:3554
skb_clone+0x1f5/0x500 net/core/skbuff.c:1282
tpacket_rcv+0x28f7/0x3200 net/packet/af_packet.c:2221
deliver_skb net/core/dev.c:1925 [inline]
deliver_ptype_list_skb net/core/dev.c:1940 [inline]
__netif_receive_skb_core+0x1bfb/0x3680 net/core/dev.c:4611
__netif_receive_skb+0x2c/0x1e0 net/core/dev.c:4693
netif_receive_skb_internal+0x12e/0x7d0 net/core/dev.c:4767
netif_receive_skb+0xbf/0x420 net/core/dev.c:4791
tun_rx_batched.isra.55+0x4ba/0x8c0 drivers/net/tun.c:1571
tun_get_user+0x2af1/0x42f0 drivers/net/tun.c:1981
tun_chr_write_iter+0xb9/0x154 drivers/net/tun.c:2009
call_write_iter include/linux/fs.h:1795 [inline]
new_sync_write fs/read_write.c:474 [inline]
__vfs_write+0x6c6/0x9f0 fs/read_write.c:487
vfs_write+0x1f8/0x560 fs/read_write.c:549
ksys_write+0x101/0x260 fs/read_write.c:598
__do_sys_write fs/read_write.c:610 [inline]
__se_sys_write fs/read_write.c:607 [inline]
__x64_sys_write+0x73/0xb0 fs/read_write.c:607
do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 4553:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kmem_cache_free+0x86/0x2d0 mm/slab.c:3756
kfree_skbmem+0x154/0x230 net/core/skbuff.c:582
__kfree_skb net/core/skbuff.c:642 [inline]
kfree_skb+0x1a5/0x580 net/core/skbuff.c:659
tpacket_rcv+0x189e/0x3200 net/packet/af_packet.c:2385
deliver_skb net/core/dev.c:1925 [inline]
deliver_ptype_list_skb net/core/dev.c:1940 [inline]
__netif_receive_skb_core+0x1bfb/0x3680 net/core/dev.c:4611
__netif_receive_skb+0x2c/0x1e0 net/core/dev.c:4693
netif_receive_skb_internal+0x12e/0x7d0 net/core/dev.c:4767
netif_receive_skb+0xbf/0x420 net/core/dev.c:4791
tun_rx_batched.isra.55+0x4ba/0x8c0 drivers/net/tun.c:1571
tun_get_user+0x2af1/0x42f0 drivers/net/tun.c:1981
tun_chr_write_iter+0xb9/0x154 drivers/net/tun.c:2009
call_write_iter include/linux/fs.h:1795 [inline]
new_sync_write fs/read_write.c:474 [inline]
__vfs_write+0x6c6/0x9f0 fs/read_write.c:487
vfs_write+0x1f8/0x560 fs/read_write.c:549
ksys_write+0x101/0x260 fs/read_write.c:598
__do_sys_write fs/read_write.c:610 [inline]
__se_sys_write fs/read_write.c:607 [inline]
__x64_sys_write+0x73/0xb0 fs/read_write.c:607
do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff8801b044ecc0
which belongs to the cache skbuff_head_cache of size 232
The buggy address is located 0 bytes inside of
232-byte region [ffff8801b044ecc0, ffff8801b044eda8)
The buggy address belongs to the page:
page:ffffea0006c11380 count:1 mapcount:0 mapping:ffff8801d9be96c0 index:0x0
flags: 0x2fffc0000000100(slab)
raw: 02fffc0000000100 ffffea0006c17988 ffff8801d9bec248 ffff8801d9be96c0
raw: 0000000000000000 ffff8801b044e040 000000010000000c 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8801b044eb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff8801b044ec00: 00 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc
>ffff8801b044ec80: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
^
ffff8801b044ed00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8801b044ed80: fb fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc
Fixes: 58d19b19cd99 ("packet: vnet_hdr support for tpacket_rcv")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2c4a47f29f36..ea601f7ca2f8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2265,6 +2265,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (po->stats.stats1.tp_drops) status |= TP_STATUS_LOSING; } + + if (do_vnet && + __packet_rcv_vnet(skb, h.raw + macoff - + sizeof(struct virtio_net_hdr))) + goto drop_n_account; + po->stats.stats1.tp_packets++; if (copy_skb) { status |= TP_STATUS_COPY; @@ -2272,14 +2278,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, } spin_unlock(&sk->sk_receive_queue.lock); - if (do_vnet) { - if (__packet_rcv_vnet(skb, h.raw + macoff - - sizeof(struct virtio_net_hdr))) { - spin_lock(&sk->sk_receive_queue.lock); - goto drop_n_account; - } - } - skb_copy_bits(skb, 0, h.raw + macoff, snaplen); if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) |