Re: net/irda: use-after-free in ircomm_param_request
On Mon, Jan 25, 2016 at 7:59 AM, Dmitry Vyukov wrote: > It seems that skb can be freed after skb_put() and spinlock unlock, > but ircomm_param_request reads skb->len afterwards: > > int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) > { > ... > skb_put(skb, count); > spin_unlock_irqrestore(&self->spinlock, flags); > pr_debug("%s(), skb->len=%d\n", __func__ , skb->len); > This looks correct to me. We can either get rid of that debugging print or move it under spinlock.
net/irda: use-after-free in ircomm_param_request
Hello, I've hit the following use-after-free report while running syzkaller fuzzer: == BUG: KASAN: use-after-free in ircomm_param_request+0x514/0x570 at addr 880035732c78 Read of size 4 by task syz-executor/10736 = BUG skbuff_head_cache (Not tainted): kasan: bad access detected - INFO: Allocated in __alloc_skb+0xba/0x5f0 age=4 cpu=1 pid=10738 [< none >] kmem_cache_alloc_node+0x93/0x2f0 mm/slub.c:2632 [< none >] __alloc_skb+0xba/0x5f0 net/core/skbuff.c:216 [< inline >] alloc_skb include/linux/skbuff.h:894 [< none >] ircomm_param_request+0x34b/0x570 net/irda/ircomm/ircomm_param.c:115 [< none >] ircomm_port_raise_dtr_rts+0x6a/0xc0 net/irda/ircomm/ircomm_tty.c:122 [< none >] tty_port_raise_dtr_rts+0x6a/0x90 drivers/tty/tty_port.c:313 [< inline >] ircomm_tty_block_til_ready net/irda/ircomm/ircomm_tty.c:291 [< none >] ircomm_tty_open+0xad7/0x12f0 net/irda/ircomm/ircomm_tty.c:462 [< none >] tty_open+0x34d/0xf80 drivers/tty/tty_io.c:2099 [< none >] chrdev_open+0x22a/0x4c0 fs/char_dev.c:388 [< none >] do_dentry_open+0x6a2/0xcb0 fs/open.c:736 [< none >] vfs_open+0x17b/0x1f0 fs/open.c:853 [< inline >] do_last fs/namei.c:3254 [< none >] path_openat+0xde9/0x5e30 fs/namei.c:3386 [< none >] do_filp_open+0x18e/0x250 fs/namei.c:3421 [< none >] do_sys_open+0x1fc/0x420 fs/open.c:1022 [< inline >] SYSC_open fs/open.c:1040 [< none >] SyS_open+0x2d/0x40 fs/open.c:1035 INFO: Freed in kfree_skbmem+0xe6/0x100 age=10 cpu=1 pid=1362 [< none >] kmem_cache_free+0x2e4/0x360 mm/slub.c:2844 [< none >] kfree_skbmem+0xe6/0x100 net/core/skbuff.c:612 [< inline >] __kfree_skb net/core/skbuff.c:674 [< none >] consume_skb+0xe4/0x2c0 net/core/skbuff.c:746 [< none >] ircomm_tty_do_softint+0x131/0x280 net/irda/ircomm/ircomm_tty.c:552 [< none >] process_one_work+0x796/0x1440 kernel/workqueue.c:2037 [< none >] worker_thread+0xdb/0xfc0 kernel/workqueue.c:2171 [< none >] kthread+0x23f/0x2d0 drivers/block/aoe/aoecmd.c:1303 [< none >] ret_from_fork+0x3f/0x70 arch/x86/entry/entry_64.S:468 INFO: Slab 0xead5cc00 objects=23 used=0 fp=0x880035732c00 flags=0x1fffc004080 INFO: Object 0x880035732c00 @offset=11264 fp=0x880035731340 CPU: 0 PID: 10736 Comm: syz-executor Tainted: GB 4.5.0-rc1+ #280 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 88b174c8 8299a06d 88003de85200 880035732c00 88003573 88b174f8 81752854 88003de85200 ead5cc00 880035732c00 0001 Call Trace: [] __asan_report_load4_noabort+0x3e/0x40 mm/kasan/report.c:294 [] ircomm_param_request+0x514/0x570 net/irda/ircomm/ircomm_param.c:140 [] ircomm_port_raise_dtr_rts+0x6a/0xc0 net/irda/ircomm/ircomm_tty.c:122 [] tty_port_raise_dtr_rts+0x6a/0x90 drivers/tty/tty_port.c:313 [< inline >] ircomm_tty_block_til_ready net/irda/ircomm/ircomm_tty.c:291 [] ircomm_tty_open+0xad7/0x12f0 net/irda/ircomm/ircomm_tty.c:462 [] tty_open+0x34d/0xf80 drivers/tty/tty_io.c:2099 [] chrdev_open+0x22a/0x4c0 fs/char_dev.c:388 [] do_dentry_open+0x6a2/0xcb0 fs/open.c:736 [] vfs_open+0x17b/0x1f0 fs/open.c:853 [< inline >] do_last fs/namei.c:3254 [] path_openat+0xde9/0x5e30 fs/namei.c:3386 [] do_filp_open+0x18e/0x250 fs/namei.c:3421 [] do_sys_open+0x1fc/0x420 fs/open.c:1022 [< inline >] SYSC_open fs/open.c:1040 [] SyS_open+0x2d/0x40 fs/open.c:1035 [] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185 == It seems that skb can be freed after skb_put() and spinlock unlock, but ircomm_param_request reads skb->len afterwards: int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) { ... skb_put(skb, count); spin_unlock_irqrestore(&self->spinlock, flags); pr_debug("%s(), skb->len=%d\n", __func__ , skb->len); On commit 92e963f50fc74041b5e9e744c330dca48e04f08d (Jan 24).