Re: WARNING in port_delete
I agree with that having a C reproducer would be much better. Now I'm working on it. I will immediately let you know once I get the C reproducer. Thank you. Best regards, DaeRyong Jeong On 24 Jul 2018, 4:00 PM +0900, Takashi Iwai , wrote: > On Tue, 24 Jul 2018 05:59:56 +0200, > DaeRyong Jeong wrote: > > > > I just realized that the crash has been spotted by Syzkaller a few days > > before. > > (https://syzkaller.appspot.com/bug?id=3490860a465e6b39227c6906f0ef2d40ad4d5bb1) > > > > I'm CC'ing Syzkaller's mailing list. > > It's very likely a false-positive sanity check, and if so, nothing > serious at all. We may simply remove two snd_BUG_ON() lines. > > But I'd love to have a C reproducer to confirm my understanding is > correct... > > > thanks, > > Takashi > > --- > --- a/sound/core/seq/seq_ports.c > +++ b/sound/core/seq/seq_ports.c > @@ -272,9 +272,6 @@ static int port_delete(struct snd_seq_client *client, > if (port->private_free) > port->private_free(port->private_data); > > - snd_BUG_ON(port->c_src.count != 0); > - snd_BUG_ON(port->c_dest.count != 0); > - > kfree(port); > return 0; > }
Re: WARNING in port_delete
I agree with that having a C reproducer would be much better. Now I'm working on it. I will immediately let you know once I get the C reproducer. Thank you. Best regards, DaeRyong Jeong On 24 Jul 2018, 4:00 PM +0900, Takashi Iwai , wrote: > On Tue, 24 Jul 2018 05:59:56 +0200, > DaeRyong Jeong wrote: > > > > I just realized that the crash has been spotted by Syzkaller a few days > > before. > > (https://syzkaller.appspot.com/bug?id=3490860a465e6b39227c6906f0ef2d40ad4d5bb1) > > > > I'm CC'ing Syzkaller's mailing list. > > It's very likely a false-positive sanity check, and if so, nothing > serious at all. We may simply remove two snd_BUG_ON() lines. > > But I'd love to have a C reproducer to confirm my understanding is > correct... > > > thanks, > > Takashi > > --- > --- a/sound/core/seq/seq_ports.c > +++ b/sound/core/seq/seq_ports.c > @@ -272,9 +272,6 @@ static int port_delete(struct snd_seq_client *client, > if (port->private_free) > port->private_free(port->private_data); > > - snd_BUG_ON(port->c_src.count != 0); > - snd_BUG_ON(port->c_dest.count != 0); > - > kfree(port); > return 0; > }
Re: KASAN: use-after-free Read in link_path_walk
Because our fuzzer has a problem, I don't have a C reproducer so far. I reported the crash becasue I saw the crash repeatedly in our fuzzer and I hoped the report is helpful. But it seems not enough. If I was wrong and I made you confused, I am really sorry for that. Could you give me a second? I am trying to fix our fuzzer and to make a C reproducer. I think the C reproducer is necessary here. On 24 Jul 2018, 2:29 PM +0900, Al Viro , wrote: > On Tue, Jul 24, 2018 at 06:17:26AM +0100, Al Viro wrote: > > On Tue, Jul 24, 2018 at 12:45:42PM +0900, Dae R. Jeong wrote: > > > Diagnosis: > > > We think that it is possible that link_path_walk() dereferences a > > > freed pointer when cleanup_mnt() is executed between path_init() and > > > link_path_walk(). > > > > > > Since I'm not an expert on a file system and don't fully understand > > > the crash, please see a executed program and a crash log below in > > > case that my understanding is wrong. > > > > > > > > > Executed Program: > > > Thread0 Thread1 > > > mkdir("./file0") > > > |--| > > > | mount("./file0", "./file0", "devpts", 0x0, "") > > > | | > > > openat(AT_FDCWD, chroot("./file0") > > > "/dev/vcs", 0x200, 0x0) umount("./file0", 0x2) > > > > > > openat(), chroot(), umount() syscalls are executed after mount() syscall. > > > We think a race occurs between openat() and chroot() because RaceFuzzer > > > executed openat() and chroot() concurrently. > > > > > > > > > (Possible) Thread interleaving: > > > CPU0 (path_openat) CPU1 (cleanup_mnt) > > Wait a bloody minute. Where does cleanup_mnt() come from in that thing? > You are doing lazy-umount of the thing you've chrooted into; if it ends > up with zero refcount on that mount, we are already in deep, deep trouble, > races with open() on not. Simply following that with stat / (in thread 1, > without thread0 at all) would end up accessing the same vfsmount. And > if it's been freed, we are well and truly fucked, race or no race. > > I really want details. *Is* cleanup_mnt() called by thread 1 in your > reproducer before the use-after-free hits? And what's the root of > thread 0 at that point?
Re: KASAN: use-after-free Read in link_path_walk
Because our fuzzer has a problem, I don't have a C reproducer so far. I reported the crash becasue I saw the crash repeatedly in our fuzzer and I hoped the report is helpful. But it seems not enough. If I was wrong and I made you confused, I am really sorry for that. Could you give me a second? I am trying to fix our fuzzer and to make a C reproducer. I think the C reproducer is necessary here. On 24 Jul 2018, 2:29 PM +0900, Al Viro , wrote: > On Tue, Jul 24, 2018 at 06:17:26AM +0100, Al Viro wrote: > > On Tue, Jul 24, 2018 at 12:45:42PM +0900, Dae R. Jeong wrote: > > > Diagnosis: > > > We think that it is possible that link_path_walk() dereferences a > > > freed pointer when cleanup_mnt() is executed between path_init() and > > > link_path_walk(). > > > > > > Since I'm not an expert on a file system and don't fully understand > > > the crash, please see a executed program and a crash log below in > > > case that my understanding is wrong. > > > > > > > > > Executed Program: > > > Thread0 Thread1 > > > mkdir("./file0") > > > |--| > > > | mount("./file0", "./file0", "devpts", 0x0, "") > > > | | > > > openat(AT_FDCWD, chroot("./file0") > > > "/dev/vcs", 0x200, 0x0) umount("./file0", 0x2) > > > > > > openat(), chroot(), umount() syscalls are executed after mount() syscall. > > > We think a race occurs between openat() and chroot() because RaceFuzzer > > > executed openat() and chroot() concurrently. > > > > > > > > > (Possible) Thread interleaving: > > > CPU0 (path_openat) CPU1 (cleanup_mnt) > > Wait a bloody minute. Where does cleanup_mnt() come from in that thing? > You are doing lazy-umount of the thing you've chrooted into; if it ends > up with zero refcount on that mount, we are already in deep, deep trouble, > races with open() on not. Simply following that with stat / (in thread 1, > without thread0 at all) would end up accessing the same vfsmount. And > if it's been freed, we are well and truly fucked, race or no race. > > I really want details. *Is* cleanup_mnt() called by thread 1 in your > reproducer before the use-after-free hits? And what's the root of > thread 0 at that point?
Re: KASAN: use-after-free Read in link_path_walk
I think that below two crashes are also related to the same race issue. KASAN: use-after-free Read in nd_jump_root, found in v4.17-rc1 KASAN: use-after-free in set_root, found in v4.18-rc3 == BUG: KASAN: use-after-free in nd_jump_root+0x69/0x160 fs/namei.c:852 Read of size 8 at addr 8801eb677e58 by task syz-executor0/20521 CPU: 0 PID: 20521 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 nd_jump_root+0x69/0x160 fs/namei.c:852 path_init+0x9ca/0x1190 fs/namei.c:2165 path_openat+0x140/0x2040 fs/namei.c:3495 do_filp_open+0x175/0x230 fs/namei.c:3535 do_sys_open+0x3c7/0x4a0 fs/open.c:1093 __do_sys_openat fs/open.c:1120 [inline] __se_sys_openat fs/open.c:1114 [inline] __x64_sys_openat+0x59/0x70 fs/open.c:1114 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x456419 RSP: 002b:7fb317cd2b28 EFLAGS: 0246 ORIG_RAX: 0101 RAX: ffda RBX: 0072bee0 RCX: 00456419 RDX: 0101 RSI: 21c0 RDI: ff9c RBP: 0497 R08: R09: R10: R11: 0246 R12: 7fb317cd36d4 R13: R14: 006fbec8 R15: Allocated by task 20521: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/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 __d_alloc+0xc0/0x6e0 fs/dcache.c:1638 d_alloc_anon fs/dcache.c:1742 [inline] d_make_root+0x2d/0x70 fs/dcache.c:1934 devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482 mount_nodev+0x59/0xd0 fs/super.c:1211 devpts_mount+0x2c/0x40 fs/devpts/inode.c:509 mount_fs+0x50/0x200 fs/super.c:1268 vfs_kern_mount.part.26+0xbc/0x2c0 fs/namespace.c:1037 vfs_kern_mount fs/namespace.c:2514 [inline] do_new_mount fs/namespace.c:2517 [inline] do_mount+0xb82/0x1bb0 fs/namespace.c:2847 ksys_mount+0xab/0x120 fs/namespace.c:3063 __do_sys_mount fs/namespace.c:3077 [inline] __se_sys_mount fs/namespace.c:3074 [inline] __x64_sys_mount+0x67/0x80 fs/namespace.c:3074 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 20522: 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+0x83/0x2a0 mm/slab.c:3756 __d_free fs/dcache.c:257 [inline] dentry_free+0x8c/0xe0 fs/dcache.c:347 __dentry_kill+0x3d6/0x440 fs/dcache.c:582 dentry_kill+0x8f/0x320 fs/dcache.c:686 dput.part.22+0x430/0x4e0 fs/dcache.c:850 dput fs/dcache.c:830 [inline] do_one_tree+0x43/0x50 fs/dcache.c:1523 shrink_dcache_for_umount+0xa5/0x1c0 fs/dcache.c:1537 generic_shutdown_super+0xb0/0x330 fs/super.c:425 kill_anon_super fs/super.c:1037 [inline] kill_litter_super+0x48/0x60 fs/super.c:1047 devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519 deactivate_locked_super+0x71/0xb0 fs/super.c:313 deactivate_super+0x10f/0x150 fs/super.c:344 cleanup_mnt+0x6b/0xc0 fs/namespace.c:1173 __cleanup_mnt+0x16/0x20 fs/namespace.c:1180 task_work_run+0x152/0x1b0 kernel/task_work.c:113 tracehook_notify_resume include/linux/tracehook.h:191 [inline] exit_to_usermode_loop+0x262/0x270 arch/x86/entry/common.c:166 prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline] syscall_return_slowpath arch/x86/entry/common.c:265 [inline] do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at 8801eb677e00 which belongs to the cache dentry(17:syz0) of size 288 The buggy address is located 88 bytes inside of 288-byte region [8801eb677e00, 8801eb677f20) The buggy address belongs to the page: page:ea0007ad9dc0 count:1 mapcount:0 mapping:8801eb677040 index:0x0 flags: 0x2fffc000100(slab) raw: 02fffc000100 8801eb677040 0001000b raw: ea0007b9d2a0 ea0007b9ed20 8801ef225300 8801ed0249c0 page dumped because: kasan: bad access detected page->mem_cgroup:8801ed0249c0 Memory state around the buggy address: 8801eb677d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 8801eb677d80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc >8801eb677e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Re: KASAN: use-after-free Read in link_path_walk
I think that below two crashes are also related to the same race issue. KASAN: use-after-free Read in nd_jump_root, found in v4.17-rc1 KASAN: use-after-free in set_root, found in v4.18-rc3 == BUG: KASAN: use-after-free in nd_jump_root+0x69/0x160 fs/namei.c:852 Read of size 8 at addr 8801eb677e58 by task syz-executor0/20521 CPU: 0 PID: 20521 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 nd_jump_root+0x69/0x160 fs/namei.c:852 path_init+0x9ca/0x1190 fs/namei.c:2165 path_openat+0x140/0x2040 fs/namei.c:3495 do_filp_open+0x175/0x230 fs/namei.c:3535 do_sys_open+0x3c7/0x4a0 fs/open.c:1093 __do_sys_openat fs/open.c:1120 [inline] __se_sys_openat fs/open.c:1114 [inline] __x64_sys_openat+0x59/0x70 fs/open.c:1114 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x456419 RSP: 002b:7fb317cd2b28 EFLAGS: 0246 ORIG_RAX: 0101 RAX: ffda RBX: 0072bee0 RCX: 00456419 RDX: 0101 RSI: 21c0 RDI: ff9c RBP: 0497 R08: R09: R10: R11: 0246 R12: 7fb317cd36d4 R13: R14: 006fbec8 R15: Allocated by task 20521: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/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 __d_alloc+0xc0/0x6e0 fs/dcache.c:1638 d_alloc_anon fs/dcache.c:1742 [inline] d_make_root+0x2d/0x70 fs/dcache.c:1934 devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482 mount_nodev+0x59/0xd0 fs/super.c:1211 devpts_mount+0x2c/0x40 fs/devpts/inode.c:509 mount_fs+0x50/0x200 fs/super.c:1268 vfs_kern_mount.part.26+0xbc/0x2c0 fs/namespace.c:1037 vfs_kern_mount fs/namespace.c:2514 [inline] do_new_mount fs/namespace.c:2517 [inline] do_mount+0xb82/0x1bb0 fs/namespace.c:2847 ksys_mount+0xab/0x120 fs/namespace.c:3063 __do_sys_mount fs/namespace.c:3077 [inline] __se_sys_mount fs/namespace.c:3074 [inline] __x64_sys_mount+0x67/0x80 fs/namespace.c:3074 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 20522: 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+0x83/0x2a0 mm/slab.c:3756 __d_free fs/dcache.c:257 [inline] dentry_free+0x8c/0xe0 fs/dcache.c:347 __dentry_kill+0x3d6/0x440 fs/dcache.c:582 dentry_kill+0x8f/0x320 fs/dcache.c:686 dput.part.22+0x430/0x4e0 fs/dcache.c:850 dput fs/dcache.c:830 [inline] do_one_tree+0x43/0x50 fs/dcache.c:1523 shrink_dcache_for_umount+0xa5/0x1c0 fs/dcache.c:1537 generic_shutdown_super+0xb0/0x330 fs/super.c:425 kill_anon_super fs/super.c:1037 [inline] kill_litter_super+0x48/0x60 fs/super.c:1047 devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519 deactivate_locked_super+0x71/0xb0 fs/super.c:313 deactivate_super+0x10f/0x150 fs/super.c:344 cleanup_mnt+0x6b/0xc0 fs/namespace.c:1173 __cleanup_mnt+0x16/0x20 fs/namespace.c:1180 task_work_run+0x152/0x1b0 kernel/task_work.c:113 tracehook_notify_resume include/linux/tracehook.h:191 [inline] exit_to_usermode_loop+0x262/0x270 arch/x86/entry/common.c:166 prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline] syscall_return_slowpath arch/x86/entry/common.c:265 [inline] do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at 8801eb677e00 which belongs to the cache dentry(17:syz0) of size 288 The buggy address is located 88 bytes inside of 288-byte region [8801eb677e00, 8801eb677f20) The buggy address belongs to the page: page:ea0007ad9dc0 count:1 mapcount:0 mapping:8801eb677040 index:0x0 flags: 0x2fffc000100(slab) raw: 02fffc000100 8801eb677040 0001000b raw: ea0007b9d2a0 ea0007b9ed20 8801ef225300 8801ed0249c0 page dumped because: kasan: bad access detected page->mem_cgroup:8801ed0249c0 Memory state around the buggy address: 8801eb677d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 8801eb677d80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc >8801eb677e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Re: WARNING in port_delete
I just realized that the crash has been spotted by Syzkaller a few days before. (https://syzkaller.appspot.com/bug?id=3490860a465e6b39227c6906f0ef2d40ad4d5bb1) I'm CC'ing Syzkaller's mailing list. Best regards, DaeRyong Jeong On Tue, Jul 24, 2018 at 12:36 PM, Dae R. Jeong wrote: > Reporting the crash: WARNING in port_delete > > This crash has been found in v4.18-rc3 using RaceFuzzer (a modified > version of Syzkaller), which we descrbie more at the end of this > report. Our analysis shows that the race occurs when invoking two close > syscalls concurrently. > > > The executed program is as follows: > r0 = open("/dev/snd/seq", 0x0, 0x0) > ioctl(r0, SNDRV_SEQ_IOCTL_CREATE_PORT, {{0x80}, > "706f729430233f77081000", > 0x, 0xfbff}) > r1 = openat(AT_FDCWD, "/dev/sequencer2", 0x8402, 0x0) > close(r0) > close(r1) > > and two threads executed the program as follows: > Thread0 Thread1 > open("/dev/snd/seq") > ioctl(r0, SNDRV_SEQ_IOCTL_CREATE_PORT) > openat("/dev/sequencer2") > close(r0) close(r1) > > (Note that two close() syscalls were exeuted after openat() syscall, and > two close() syscalls were executed concurrently.) > > > Crash log: > == > WARNING: CPU: 1 PID: 32519 at > /home/daeryong/workspace/race-fuzzer/kernels_repo/kernel_v4.18-rc3/sound/core/seq/seq_ports.c:275 > port_delete+0xde/0xf0 sound/core/seq/seq_ports.c:275 > Kernel panic - not syncing: panic_on_warn set ... > > CPU: 1 PID: 32519 Comm: syz-executor0 Not tainted 4.18.0-rc3 #1 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS > rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > Call Trace: > __dump_stack lib/dump_stack.c:77 [inline] > dump_stack+0x16e/0x22c lib/dump_stack.c:113 > panic+0x1a8/0x3a7 kernel/panic.c:184 > __warn+0x191/0x1a0 kernel/panic.c:536 > report_bug+0x132/0x1b0 lib/bug.c:186 > fixup_bug.part.10+0x28/0x50 arch/x86/kernel/traps.c:178 > fixup_bug arch/x86/kernel/traps.c:247 [inline] > do_error_trap+0x284/0x2c0 arch/x86/kernel/traps.c:296 > do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:316 > invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 > RIP: 0010:port_delete+0xde/0xf0 sound/core/seq/seq_ports.c:275 > Code: 00 00 e8 b5 68 d2 fd 8b 83 58 01 00 00 85 c0 75 1d e8 86 5c ae fd 48 89 > df e8 3e 52 d2 fd 31 c0 5b 41 5c 5d c3 e8 72 5c ae fd <0f> 0b eb c8 e8 69 5c > ae fd 0f 0b eb da 0f 1f 44 00 00 55 48 89 e5 > RSP: 0018:8801d635f900 EFLAGS: 00010216 > RAX: 0004 RBX: 8801da196900 RCX: 839b86ee > RDX: 5e94 RSI: c9000264 RDI: 8801da196978 > RBP: 8801d635f910 R08: 0098 R09: > R10: R11: R12: 839ba820 > R13: 8801da196950 R14: 8801ed5bc080 R15: 8801da196958 > snd_seq_delete_port+0x2b0/0x2d0 sound/core/seq/seq_ports.c:303 > snd_seq_ioctl_delete_port+0x5b/0xa0 sound/core/seq/seq_clientmgr.c:1325 > snd_seq_kernel_client_ctl+0xd4/0xf0 sound/core/seq/seq_clientmgr.c:2361 > snd_seq_event_port_detach+0xcb/0x120 sound/core/seq/seq_ports.c:705 > delete_port+0x3a/0x70 sound/core/seq/oss/seq_oss_init.c:354 > snd_seq_oss_release+0x7c/0x90 sound/core/seq/oss/seq_oss_init.c:433 > odev_release+0x40/0x60 sound/core/seq/oss/seq_oss.c:153 > __fput+0x234/0x470 fs/file_table.c:209 > fput+0x15/0x20 fs/file_table.c:243 > task_work_run+0x15a/0x1c0 kernel/task_work.c:113 > tracehook_notify_resume include/linux/tracehook.h:192 [inline] > exit_to_usermode_loop+0x2a3/0x2b0 arch/x86/entry/common.c:166 > prepare_exit_to_usermode arch/x86/entry/common.c:197 [inline] > syscall_return_slowpath arch/x86/entry/common.c:268 [inline] > do_syscall_64+0x485/0x4b0 arch/x86/entry/common.c:293 > entry_SYSCALL_64_after_hwframe+0x49/0xbe > RIP: 0033:0x456469 > Code: 1d ba fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 > 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f > 83 eb b9 fb ff c3 66 2e 0f 1f 84 00 00 00 00 > RSP: 002b:7fe9a8936b28 EFLAGS: 0246 ORIG_RAX: 0003 > RAX: RBX: 0072bfa0 RCX: 00456469 > RDX: RSI: RDI: 0014 > RBP: 0054 R08: R09: > R10: R11: 0246 R12: 7fe9a89376d4 > R13: R14: 006f5880 R15: > Dumping ftrace buffer: >(ftrace buffer
Re: WARNING in port_delete
I just realized that the crash has been spotted by Syzkaller a few days before. (https://syzkaller.appspot.com/bug?id=3490860a465e6b39227c6906f0ef2d40ad4d5bb1) I'm CC'ing Syzkaller's mailing list. Best regards, DaeRyong Jeong On Tue, Jul 24, 2018 at 12:36 PM, Dae R. Jeong wrote: > Reporting the crash: WARNING in port_delete > > This crash has been found in v4.18-rc3 using RaceFuzzer (a modified > version of Syzkaller), which we descrbie more at the end of this > report. Our analysis shows that the race occurs when invoking two close > syscalls concurrently. > > > The executed program is as follows: > r0 = open("/dev/snd/seq", 0x0, 0x0) > ioctl(r0, SNDRV_SEQ_IOCTL_CREATE_PORT, {{0x80}, > "706f729430233f77081000", > 0x, 0xfbff}) > r1 = openat(AT_FDCWD, "/dev/sequencer2", 0x8402, 0x0) > close(r0) > close(r1) > > and two threads executed the program as follows: > Thread0 Thread1 > open("/dev/snd/seq") > ioctl(r0, SNDRV_SEQ_IOCTL_CREATE_PORT) > openat("/dev/sequencer2") > close(r0) close(r1) > > (Note that two close() syscalls were exeuted after openat() syscall, and > two close() syscalls were executed concurrently.) > > > Crash log: > == > WARNING: CPU: 1 PID: 32519 at > /home/daeryong/workspace/race-fuzzer/kernels_repo/kernel_v4.18-rc3/sound/core/seq/seq_ports.c:275 > port_delete+0xde/0xf0 sound/core/seq/seq_ports.c:275 > Kernel panic - not syncing: panic_on_warn set ... > > CPU: 1 PID: 32519 Comm: syz-executor0 Not tainted 4.18.0-rc3 #1 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS > rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > Call Trace: > __dump_stack lib/dump_stack.c:77 [inline] > dump_stack+0x16e/0x22c lib/dump_stack.c:113 > panic+0x1a8/0x3a7 kernel/panic.c:184 > __warn+0x191/0x1a0 kernel/panic.c:536 > report_bug+0x132/0x1b0 lib/bug.c:186 > fixup_bug.part.10+0x28/0x50 arch/x86/kernel/traps.c:178 > fixup_bug arch/x86/kernel/traps.c:247 [inline] > do_error_trap+0x284/0x2c0 arch/x86/kernel/traps.c:296 > do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:316 > invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 > RIP: 0010:port_delete+0xde/0xf0 sound/core/seq/seq_ports.c:275 > Code: 00 00 e8 b5 68 d2 fd 8b 83 58 01 00 00 85 c0 75 1d e8 86 5c ae fd 48 89 > df e8 3e 52 d2 fd 31 c0 5b 41 5c 5d c3 e8 72 5c ae fd <0f> 0b eb c8 e8 69 5c > ae fd 0f 0b eb da 0f 1f 44 00 00 55 48 89 e5 > RSP: 0018:8801d635f900 EFLAGS: 00010216 > RAX: 0004 RBX: 8801da196900 RCX: 839b86ee > RDX: 5e94 RSI: c9000264 RDI: 8801da196978 > RBP: 8801d635f910 R08: 0098 R09: > R10: R11: R12: 839ba820 > R13: 8801da196950 R14: 8801ed5bc080 R15: 8801da196958 > snd_seq_delete_port+0x2b0/0x2d0 sound/core/seq/seq_ports.c:303 > snd_seq_ioctl_delete_port+0x5b/0xa0 sound/core/seq/seq_clientmgr.c:1325 > snd_seq_kernel_client_ctl+0xd4/0xf0 sound/core/seq/seq_clientmgr.c:2361 > snd_seq_event_port_detach+0xcb/0x120 sound/core/seq/seq_ports.c:705 > delete_port+0x3a/0x70 sound/core/seq/oss/seq_oss_init.c:354 > snd_seq_oss_release+0x7c/0x90 sound/core/seq/oss/seq_oss_init.c:433 > odev_release+0x40/0x60 sound/core/seq/oss/seq_oss.c:153 > __fput+0x234/0x470 fs/file_table.c:209 > fput+0x15/0x20 fs/file_table.c:243 > task_work_run+0x15a/0x1c0 kernel/task_work.c:113 > tracehook_notify_resume include/linux/tracehook.h:192 [inline] > exit_to_usermode_loop+0x2a3/0x2b0 arch/x86/entry/common.c:166 > prepare_exit_to_usermode arch/x86/entry/common.c:197 [inline] > syscall_return_slowpath arch/x86/entry/common.c:268 [inline] > do_syscall_64+0x485/0x4b0 arch/x86/entry/common.c:293 > entry_SYSCALL_64_after_hwframe+0x49/0xbe > RIP: 0033:0x456469 > Code: 1d ba fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 > 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f > 83 eb b9 fb ff c3 66 2e 0f 1f 84 00 00 00 00 > RSP: 002b:7fe9a8936b28 EFLAGS: 0246 ORIG_RAX: 0003 > RAX: RBX: 0072bfa0 RCX: 00456469 > RDX: RSI: RDI: 0014 > RBP: 0054 R08: R09: > R10: R11: 0246 R12: 7fe9a89376d4 > R13: R14: 006f5880 R15: > Dumping ftrace buffer: >(ftrace buffer
Re: KASAN: use-after-free Read in vhost_chr_write_iter
On Mon, May 21, 2018 at 10:38:10AM +0800, Jason Wang wrote: > > > On 2018年05月18日 17:24, Jason Wang wrote: > > > > > > On 2018年05月17日 21:45, DaeRyong Jeong wrote: > > > We report the crash: KASAN: use-after-free Read in vhost_chr_write_iter > > > > > > This crash has been found in v4.17-rc1 using RaceFuzzer (a modified > > > version of Syzkaller), which we describe more at the end of this > > > report. Our analysis shows that the race occurs when invoking two > > > syscalls concurrently, write$vnet and ioctl$VHOST_RESET_OWNER. > > > > > > > > > Analysis: > > > We think the concurrent execution of vhost_process_iotlb_msg() and > > > vhost_dev_cleanup() causes the crash. > > > Both of functions can run concurrently (please see call sequence below), > > > and possibly, there is a race on dev->iotlb. > > > If the switch occurs right after vhost_dev_cleanup() frees > > > dev->iotlb, vhost_process_iotlb_msg() still sees the non-null value > > > and it > > > keep executing without returning -EFAULT. Consequently, use-after-free > > > occures > > > > > > > > > Thread interleaving: > > > CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) > > > (In the case of both VHOST_IOTLB_UPDATE and > > > VHOST_IOTLB_INVALIDATE) > > > = = > > > vhost_umem_clean(dev->iotlb); > > > if (!dev->iotlb) { > > > ret = -EFAULT; > > > break; > > > } > > > dev->iotlb = NULL; > > > > > > > > > Call Sequence: > > > CPU0 > > > = > > > vhost_net_chr_write_iter > > > vhost_chr_write_iter > > > vhost_process_iotlb_msg > > > > > > CPU1 > > > = > > > vhost_net_ioctl > > > vhost_net_reset_owner > > > vhost_dev_reset_owner > > > vhost_dev_cleanup > > > > Thanks a lot for the analysis. > > > > This could be addressed by simply protect it with dev mutex. > > > > Will post a patch. > > > > Could you please help to test the attached patch? I've done some smoking > test. > > Thanks Sorry to say this, but we don't have a reproducer for this bug since our reproducer is being implemented. This crash had occrued a few times in our fuzzer, so I inspected the code manually. It seems the patch is good for me, but we can't test the patch for now. Sorry. > From 88328386f3f652e684ee33dc4cf63dcaed871aea Mon Sep 17 00:00:00 2001 > From: Jason Wang <jasow...@redhat.com> > Date: Fri, 18 May 2018 17:33:27 +0800 > Subject: [PATCH] vhost: synchronize IOTLB message with dev cleanup > > DaeRyong Jeong reports a race between vhost_dev_cleanup() and > vhost_process_iotlb_msg(): > > Thread interleaving: > CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) > (In the case of both VHOST_IOTLB_UPDATE and > VHOST_IOTLB_INVALIDATE) > = = > vhost_umem_clean(dev->iotlb); > if (!dev->iotlb) { > ret = -EFAULT; > break; > } > dev->iotlb = NULL; > > The reason is we don't synchronize between them, fixing by protecting > vhost_process_iotlb_msg() with dev mutex. > > Reported-by: DaeRyong Jeong <threeear...@gmail.com> > Fixes: 6b1e6cc7855b0 ("vhost: new device IOTLB API") > Reported-by: DaeRyong Jeong <threeear...@gmail.com> > --- > drivers/vhost/vhost.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c > index f3bd8e9..f0be5f3 100644 > --- a/drivers/vhost/vhost.c > +++ b/drivers/vhost/vhost.c > @@ -981,6 +981,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, > { > int ret = 0; > > + mutex_lock(>mutex); > vhost_dev_lock_vqs(dev); > switch (msg->type) { > case VHOST_IOTLB_UPDATE: > @@ -1016,6 +1017,8 @@ static int vhost_process_iotlb_msg(struct vhost_dev > *dev, > } > > vhost_dev_unlock_vqs(dev); > + mutex_unlock(>mutex); > + > return ret; > } > ssize_t vhost_chr_write_iter(struct vhost_dev *dev, > -- > 2.7.4 >
Re: KASAN: use-after-free Read in vhost_chr_write_iter
On Mon, May 21, 2018 at 10:38:10AM +0800, Jason Wang wrote: > > > On 2018年05月18日 17:24, Jason Wang wrote: > > > > > > On 2018年05月17日 21:45, DaeRyong Jeong wrote: > > > We report the crash: KASAN: use-after-free Read in vhost_chr_write_iter > > > > > > This crash has been found in v4.17-rc1 using RaceFuzzer (a modified > > > version of Syzkaller), which we describe more at the end of this > > > report. Our analysis shows that the race occurs when invoking two > > > syscalls concurrently, write$vnet and ioctl$VHOST_RESET_OWNER. > > > > > > > > > Analysis: > > > We think the concurrent execution of vhost_process_iotlb_msg() and > > > vhost_dev_cleanup() causes the crash. > > > Both of functions can run concurrently (please see call sequence below), > > > and possibly, there is a race on dev->iotlb. > > > If the switch occurs right after vhost_dev_cleanup() frees > > > dev->iotlb, vhost_process_iotlb_msg() still sees the non-null value > > > and it > > > keep executing without returning -EFAULT. Consequently, use-after-free > > > occures > > > > > > > > > Thread interleaving: > > > CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) > > > (In the case of both VHOST_IOTLB_UPDATE and > > > VHOST_IOTLB_INVALIDATE) > > > = = > > > vhost_umem_clean(dev->iotlb); > > > if (!dev->iotlb) { > > > ret = -EFAULT; > > > break; > > > } > > > dev->iotlb = NULL; > > > > > > > > > Call Sequence: > > > CPU0 > > > = > > > vhost_net_chr_write_iter > > > vhost_chr_write_iter > > > vhost_process_iotlb_msg > > > > > > CPU1 > > > = > > > vhost_net_ioctl > > > vhost_net_reset_owner > > > vhost_dev_reset_owner > > > vhost_dev_cleanup > > > > Thanks a lot for the analysis. > > > > This could be addressed by simply protect it with dev mutex. > > > > Will post a patch. > > > > Could you please help to test the attached patch? I've done some smoking > test. > > Thanks Sorry to say this, but we don't have a reproducer for this bug since our reproducer is being implemented. This crash had occrued a few times in our fuzzer, so I inspected the code manually. It seems the patch is good for me, but we can't test the patch for now. Sorry. > From 88328386f3f652e684ee33dc4cf63dcaed871aea Mon Sep 17 00:00:00 2001 > From: Jason Wang > Date: Fri, 18 May 2018 17:33:27 +0800 > Subject: [PATCH] vhost: synchronize IOTLB message with dev cleanup > > DaeRyong Jeong reports a race between vhost_dev_cleanup() and > vhost_process_iotlb_msg(): > > Thread interleaving: > CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) > (In the case of both VHOST_IOTLB_UPDATE and > VHOST_IOTLB_INVALIDATE) > = = > vhost_umem_clean(dev->iotlb); > if (!dev->iotlb) { > ret = -EFAULT; > break; > } > dev->iotlb = NULL; > > The reason is we don't synchronize between them, fixing by protecting > vhost_process_iotlb_msg() with dev mutex. > > Reported-by: DaeRyong Jeong > Fixes: 6b1e6cc7855b0 ("vhost: new device IOTLB API") > Reported-by: DaeRyong Jeong > --- > drivers/vhost/vhost.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c > index f3bd8e9..f0be5f3 100644 > --- a/drivers/vhost/vhost.c > +++ b/drivers/vhost/vhost.c > @@ -981,6 +981,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, > { > int ret = 0; > > + mutex_lock(>mutex); > vhost_dev_lock_vqs(dev); > switch (msg->type) { > case VHOST_IOTLB_UPDATE: > @@ -1016,6 +1017,8 @@ static int vhost_process_iotlb_msg(struct vhost_dev > *dev, > } > > vhost_dev_unlock_vqs(dev); > + mutex_unlock(>mutex); > + > return ret; > } > ssize_t vhost_chr_write_iter(struct vhost_dev *dev, > -- > 2.7.4 >
WARNING in ip_recv_error
We report the crash: WARNING in ip_recv_error (I resend the email since I mistakenly missed the subject in my previous email. I'm sorry.) This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, setsockopt$inet6_IPV6_ADDRFORM and recvmsg. Diagnosis: We think the concurrent execution of do_ipv6_setsockopt() with optname IPV6_ADDRFORM and inet_recvmsg() causes the crash. do_ipv6_setsockopt() can update sk->prot to _prot and sk->sk_family to PF_INET. But inet_recvmsg() can execute sk->sk_prot->recvmsg() right after that sk->prot is updated and sk->sk_family is not updated by do_ipv6_setsockopt(). This will lead WARN_ON in ip_recv_error(). Thread interleaving: CPU0 (do_ipv6_setsockopt) CPU1 (inet_recvmsg) = = struct proto *prot = _prot; ... sk->sk_prot = prot; sk->sk_socket->ops = _dgram_ops; err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, _len); (in udp_recvmsg) if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len, addr_len); (in ip_recv_error) WARN_ON_ONCE(sk->sk_family == AF_INET6); sk->sk_family = PF_INET; Call Sequence: CPU0 = udpv6_setsockopt ipv6_setsockopt do_ipv6_setsockopt CPU1 = sock_recvmsg sock_recvmsg_nosec inet_recvmsg udp_recvmsg == WARNING: CPU: 1 PID: 32600 at /home/daeryong/workspace/new-race-fuzzer/kernels_repo/kernel_v4.17-rc1/net/ipv4/ip_sockglue.c:508 ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 32600 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 panic+0x1a0/0x3a7 kernel/panic.c:184 __warn+0x191/0x1a0 kernel/panic.c:536 report_bug+0x132/0x1b0 lib/bug.c:186 fixup_bug.part.11+0x28/0x50 arch/x86/kernel/traps.c:178 fixup_bug arch/x86/kernel/traps.c:247 [inline] do_error_trap+0x28b/0x2d0 arch/x86/kernel/traps.c:296 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 RIP: 0010:ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 RSP: 0018:8801dadff630 EFLAGS: 00010212 RAX: 0004 RBX: 2002 RCX: 8327de12 RDX: 008a RSI: c90001a0c000 RDI: 8801be615010 RBP: 8801dadff720 R08: 2002 R09: 8801dadff918 R10: 8801dadff738 R11: 8801dadffaff R12: 8801be615000 R13: 8801dadffd50 R14: 11003b5bfece R15: 8801dadffb90 udp_recvmsg+0x834/0xa10 net/ipv4/udp.c:1571 inet_recvmsg+0x121/0x420 net/ipv4/af_inet.c:830 sock_recvmsg_nosec net/socket.c:802 [inline] sock_recvmsg+0x7f/0xa0 net/socket.c:809 ___sys_recvmsg+0x1f0/0x430 net/socket.c:2279 __sys_recvmsg+0xfc/0x1c0 net/socket.c:2328 __do_sys_recvmsg net/socket.c:2338 [inline] __se_sys_recvmsg net/socket.c:2335 [inline] __x64_sys_recvmsg+0x48/0x50 net/socket.c:2335 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f24f6927b28 EFLAGS: 0246 ORIG_RAX: 002f RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 2002 RSI: 2240 RDI: 0016 RBP: 04e4 R08: R09: R10: R11: 0246 R12: 7f24f69286d4 R13: R14: 006fc600 R15: Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled Rebooting in 86400 seconds.. == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness
WARNING in ip_recv_error
We report the crash: WARNING in ip_recv_error (I resend the email since I mistakenly missed the subject in my previous email. I'm sorry.) This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, setsockopt$inet6_IPV6_ADDRFORM and recvmsg. Diagnosis: We think the concurrent execution of do_ipv6_setsockopt() with optname IPV6_ADDRFORM and inet_recvmsg() causes the crash. do_ipv6_setsockopt() can update sk->prot to _prot and sk->sk_family to PF_INET. But inet_recvmsg() can execute sk->sk_prot->recvmsg() right after that sk->prot is updated and sk->sk_family is not updated by do_ipv6_setsockopt(). This will lead WARN_ON in ip_recv_error(). Thread interleaving: CPU0 (do_ipv6_setsockopt) CPU1 (inet_recvmsg) = = struct proto *prot = _prot; ... sk->sk_prot = prot; sk->sk_socket->ops = _dgram_ops; err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, _len); (in udp_recvmsg) if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len, addr_len); (in ip_recv_error) WARN_ON_ONCE(sk->sk_family == AF_INET6); sk->sk_family = PF_INET; Call Sequence: CPU0 = udpv6_setsockopt ipv6_setsockopt do_ipv6_setsockopt CPU1 = sock_recvmsg sock_recvmsg_nosec inet_recvmsg udp_recvmsg == WARNING: CPU: 1 PID: 32600 at /home/daeryong/workspace/new-race-fuzzer/kernels_repo/kernel_v4.17-rc1/net/ipv4/ip_sockglue.c:508 ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 32600 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 panic+0x1a0/0x3a7 kernel/panic.c:184 __warn+0x191/0x1a0 kernel/panic.c:536 report_bug+0x132/0x1b0 lib/bug.c:186 fixup_bug.part.11+0x28/0x50 arch/x86/kernel/traps.c:178 fixup_bug arch/x86/kernel/traps.c:247 [inline] do_error_trap+0x28b/0x2d0 arch/x86/kernel/traps.c:296 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 RIP: 0010:ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 RSP: 0018:8801dadff630 EFLAGS: 00010212 RAX: 0004 RBX: 2002 RCX: 8327de12 RDX: 008a RSI: c90001a0c000 RDI: 8801be615010 RBP: 8801dadff720 R08: 2002 R09: 8801dadff918 R10: 8801dadff738 R11: 8801dadffaff R12: 8801be615000 R13: 8801dadffd50 R14: 11003b5bfece R15: 8801dadffb90 udp_recvmsg+0x834/0xa10 net/ipv4/udp.c:1571 inet_recvmsg+0x121/0x420 net/ipv4/af_inet.c:830 sock_recvmsg_nosec net/socket.c:802 [inline] sock_recvmsg+0x7f/0xa0 net/socket.c:809 ___sys_recvmsg+0x1f0/0x430 net/socket.c:2279 __sys_recvmsg+0xfc/0x1c0 net/socket.c:2328 __do_sys_recvmsg net/socket.c:2338 [inline] __se_sys_recvmsg net/socket.c:2335 [inline] __x64_sys_recvmsg+0x48/0x50 net/socket.c:2335 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f24f6927b28 EFLAGS: 0246 ORIG_RAX: 002f RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 2002 RSI: 2240 RDI: 0016 RBP: 04e4 R08: R09: R10: R11: 0246 R12: 7f24f69286d4 R13: R14: 006fc600 R15: Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled Rebooting in 86400 seconds.. == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness
[no subject]
Bcc: Subject: WARNING in ip_recv_error Reply-To: We report the crash: WARNING in ip_recv_error This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, do_ipv6_setsockopt and inet_recvmsg. Diagnosis: We think the concurrent execution of do_ipv6_setsockopt() with optname IPV6_ADDRFORM and inet_recvmsg() causes the crash. do_ipv6_setsockopt() can update sk->prot to _prot and sk->sk_family to PF_INET. But inet_recvmsg() can execute sk->sk_prot->recvmsg() right after that sk->prot is updated and sk->sk_family is not updated by do_ipv6_setsockopt(). This will lead WARN_ON in ip_recv_error(). Thread interleaving: CPU0 (do_ipv6_setsockopt) CPU1 (inet_recvmsg) = = struct proto *prot = _prot; ... sk->sk_prot = prot; sk->sk_socket->ops = _dgram_ops; err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, _len); (in udp_recvmsg) if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len, addr_len); (in ip_recv_error) WARN_ON_ONCE(sk->sk_family == AF_INET6); sk->sk_family = PF_INET; Call Sequence: CPU0 = udpv6_setsockopt ipv6_setsockopt do_ipv6_setsockopt CPU1 = sock_recvmsg sock_recvmsg_nosec inet_recvmsg udp_recvmsg == WARNING: CPU: 1 PID: 32600 at /home/daeryong/workspace/new-race-fuzzer/kernels_repo/kernel_v4.17-rc1/net/ipv4/ip_sockglue.c:508 ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 32600 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 panic+0x1a0/0x3a7 kernel/panic.c:184 __warn+0x191/0x1a0 kernel/panic.c:536 report_bug+0x132/0x1b0 lib/bug.c:186 fixup_bug.part.11+0x28/0x50 arch/x86/kernel/traps.c:178 fixup_bug arch/x86/kernel/traps.c:247 [inline] do_error_trap+0x28b/0x2d0 arch/x86/kernel/traps.c:296 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 RIP: 0010:ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 RSP: 0018:8801dadff630 EFLAGS: 00010212 RAX: 0004 RBX: 2002 RCX: 8327de12 RDX: 008a RSI: c90001a0c000 RDI: 8801be615010 RBP: 8801dadff720 R08: 2002 R09: 8801dadff918 R10: 8801dadff738 R11: 8801dadffaff R12: 8801be615000 R13: 8801dadffd50 R14: 11003b5bfece R15: 8801dadffb90 udp_recvmsg+0x834/0xa10 net/ipv4/udp.c:1571 inet_recvmsg+0x121/0x420 net/ipv4/af_inet.c:830 sock_recvmsg_nosec net/socket.c:802 [inline] sock_recvmsg+0x7f/0xa0 net/socket.c:809 ___sys_recvmsg+0x1f0/0x430 net/socket.c:2279 __sys_recvmsg+0xfc/0x1c0 net/socket.c:2328 __do_sys_recvmsg net/socket.c:2338 [inline] __se_sys_recvmsg net/socket.c:2335 [inline] __x64_sys_recvmsg+0x48/0x50 net/socket.c:2335 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f24f6927b28 EFLAGS: 0246 ORIG_RAX: 002f RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 2002 RSI: 2240 RDI: 0016 RBP: 04e4 R08: R09: R10: R11: 0246 R12: 7f24f69286d4 R13: R14: 006fc600 R15: Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled Rebooting in 86400 seconds.. == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always
[no subject]
Bcc: Subject: WARNING in ip_recv_error Reply-To: We report the crash: WARNING in ip_recv_error This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, do_ipv6_setsockopt and inet_recvmsg. Diagnosis: We think the concurrent execution of do_ipv6_setsockopt() with optname IPV6_ADDRFORM and inet_recvmsg() causes the crash. do_ipv6_setsockopt() can update sk->prot to _prot and sk->sk_family to PF_INET. But inet_recvmsg() can execute sk->sk_prot->recvmsg() right after that sk->prot is updated and sk->sk_family is not updated by do_ipv6_setsockopt(). This will lead WARN_ON in ip_recv_error(). Thread interleaving: CPU0 (do_ipv6_setsockopt) CPU1 (inet_recvmsg) = = struct proto *prot = _prot; ... sk->sk_prot = prot; sk->sk_socket->ops = _dgram_ops; err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, _len); (in udp_recvmsg) if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len, addr_len); (in ip_recv_error) WARN_ON_ONCE(sk->sk_family == AF_INET6); sk->sk_family = PF_INET; Call Sequence: CPU0 = udpv6_setsockopt ipv6_setsockopt do_ipv6_setsockopt CPU1 = sock_recvmsg sock_recvmsg_nosec inet_recvmsg udp_recvmsg == WARNING: CPU: 1 PID: 32600 at /home/daeryong/workspace/new-race-fuzzer/kernels_repo/kernel_v4.17-rc1/net/ipv4/ip_sockglue.c:508 ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 32600 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 panic+0x1a0/0x3a7 kernel/panic.c:184 __warn+0x191/0x1a0 kernel/panic.c:536 report_bug+0x132/0x1b0 lib/bug.c:186 fixup_bug.part.11+0x28/0x50 arch/x86/kernel/traps.c:178 fixup_bug arch/x86/kernel/traps.c:247 [inline] do_error_trap+0x28b/0x2d0 arch/x86/kernel/traps.c:296 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992 RIP: 0010:ip_recv_error+0x6f2/0x720 net/ipv4/ip_sockglue.c:508 RSP: 0018:8801dadff630 EFLAGS: 00010212 RAX: 0004 RBX: 2002 RCX: 8327de12 RDX: 008a RSI: c90001a0c000 RDI: 8801be615010 RBP: 8801dadff720 R08: 2002 R09: 8801dadff918 R10: 8801dadff738 R11: 8801dadffaff R12: 8801be615000 R13: 8801dadffd50 R14: 11003b5bfece R15: 8801dadffb90 udp_recvmsg+0x834/0xa10 net/ipv4/udp.c:1571 inet_recvmsg+0x121/0x420 net/ipv4/af_inet.c:830 sock_recvmsg_nosec net/socket.c:802 [inline] sock_recvmsg+0x7f/0xa0 net/socket.c:809 ___sys_recvmsg+0x1f0/0x430 net/socket.c:2279 __sys_recvmsg+0xfc/0x1c0 net/socket.c:2328 __do_sys_recvmsg net/socket.c:2338 [inline] __se_sys_recvmsg net/socket.c:2335 [inline] __x64_sys_recvmsg+0x48/0x50 net/socket.c:2335 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f24f6927b28 EFLAGS: 0246 ORIG_RAX: 002f RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 2002 RSI: 2240 RDI: 0016 RBP: 04e4 R08: R09: R10: R11: 0246 R12: 7f24f69286d4 R13: R14: 006fc600 R15: Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled Rebooting in 86400 seconds.. == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always
WARNING in __static_key_slow_dec
We report the crash: WARNING in __static_key_slow_dec This crash has been found in v4.8 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Even though v4.8 is the relatively old version, we did manual verification and we think the bug still exists. Our analysis shows that the race occurs when invoking two syscalls concurrently, setsockopt() with optname SO_TIMESTAMPING and ioctl() with cmd SIOCGSTAMPNS. Diagnosis: We think if timestamp was previously enabled with SOCK_TIMESTAMPING_RX_SOFTWARE flag, the concurrent execution of sock_disable_timestamp() and sock_enable_timestamp() causes the crash. Thread interleaving: (Assume sk->flag has the SOCK_TIMESTAMPING_RX_SOFTWARE flag by the previous setsockopt() call with SO_TIMESTAMPING) CPU0 (sock_disable_timestamp()) CPU1 (sock_enable_timestamp()) = = (flag == 1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) (flag == SOCK_TIMESTAMP) if (!sock_flag(sk, flag)) { unsigned long previous_flags = sk->sk_flags; if (sk->sk_flags & flags) { sk->sk_flags &= ~flags; if (sock_needs_netstamp(sk) && !(sk->sk_flags & SK_FLAGS_TIMESTAMP)) net_disable_timestamp(); sock_set_flag(sk, flag); if (sock_needs_netstamp(sk) && !(previous_flags & SK_FLAGS_TIMESTAMP)) net_enable_timestamp(); /* Here, net_enable_timestamp() is not called because * previous_flags has the SOCK_TIMESTAMPING_RX_SOFTWARE * flag */ /* After the race, sk->sk has the flag SOCK_TIMESTAMP, but * net_enable_timestamp() is not called one more time. * Consequently, when the socket is closed, __sk_destruct() * calls net_disable_timestamp() that leads WARNING. */ Call Sequence: CPU0 = sock_setsockopt (SO_TIMESTAMPING) sock_disable_timestamp CPU1 = inet_ioctl (SIOCGSTAMPNS) sock_get_timestampns sock_enable_timestamp == [ cut here ] WARNING: CPU: 1 PID: 14465 at /home/blee/project/race-fuzzer/kernels/kernel_v4.8/kernel/jump_label.c:151 __static_key_slow_dec+0xc7/0xd0 kernel/jump_label.c:150 jump label: negative count! Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 14465 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 8801f2f5f608 81694cc3 82445d20 8801f2f5f6e0 82498700 8801f2f5f6e0 8801f2f5f6d0 812534a0 41b58ab3 829cae04 81253336 Call Trace: [] __dump_stack lib/dump_stack.c:15 [inline] [] dump_stack+0xb3/0x110 lib/dump_stack.c:51 [] panic+0x16a/0x336 kernel/panic.c:153 [] __warn+0x164/0x170 kernel/panic.c:509 [] warn_slowpath_fmt+0xac/0xd0 kernel/panic.c:532 [] __static_key_slow_dec+0xc7/0xd0 kernel/jump_label.c:150 [] static_key_slow_dec+0x33/0x60 kernel/jump_label.c:174 [] net_disable_timestamp+0x3b/0x50 net/core/dev.c:1729 [] sock_disable_timestamp+0x6e/0x80 net/core/sock.c:403 [] __sk_destruct+0xd4/0x260 net/core/sock.c:1453 [] sk_destruct+0x32/0x60 net/core/sock.c:1472 [] __sk_free+0x72/0x140 net/core/sock.c:1480 [] sk_free+0x23/0x30 net/core/sock.c:1491 [] sock_put include/net/sock.h:1582 [inline] [] sk_common_release+0x1ac/0x250 net/core/sock.c:2766 [] raw_close+0x21/0x30 net/ipv4/raw.c:687 [] inet_release+0x80/0xd0 net/ipv4/af_inet.c:420 [] sock_release+0x4e/0xf0 net/socket.c:573 [] sock_close+0x16/0x20 net/socket.c:1020 [] __fput+0x182/0x380 fs/file_table.c:208 [] fput+0x15/0x20 fs/file_table.c:244 [] task_work_run+0xcb/0x100 kernel/task_work.c:116 [] exit_task_work include/linux/task_work.h:21 [inline] [] do_exit+0x5a1/0x17f0 kernel/exit.c:828 [] do_group_exit+0xa7/0x190 kernel/exit.c:953 [] get_signal+0x465/0xdf0 kernel/signal.c:2307 [] do_signal+0x93/0xad0 arch/x86/kernel/signal.c:805 [] exit_to_usermode_loop+0xe0/0x110 arch/x86/entry/common.c:163 [] prepare_exit_to_usermode arch/x86/entry/common.c:198 [inline] [] syscall_return_slowpath+0x146/0x150 arch/x86/entry/common.c:267 [] entry_SYSCALL_64_fastpath+0xbb/0xbd Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled == = About RaceFuzzer RaceFuzzer is a customized version
WARNING in __static_key_slow_dec
We report the crash: WARNING in __static_key_slow_dec This crash has been found in v4.8 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Even though v4.8 is the relatively old version, we did manual verification and we think the bug still exists. Our analysis shows that the race occurs when invoking two syscalls concurrently, setsockopt() with optname SO_TIMESTAMPING and ioctl() with cmd SIOCGSTAMPNS. Diagnosis: We think if timestamp was previously enabled with SOCK_TIMESTAMPING_RX_SOFTWARE flag, the concurrent execution of sock_disable_timestamp() and sock_enable_timestamp() causes the crash. Thread interleaving: (Assume sk->flag has the SOCK_TIMESTAMPING_RX_SOFTWARE flag by the previous setsockopt() call with SO_TIMESTAMPING) CPU0 (sock_disable_timestamp()) CPU1 (sock_enable_timestamp()) = = (flag == 1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) (flag == SOCK_TIMESTAMP) if (!sock_flag(sk, flag)) { unsigned long previous_flags = sk->sk_flags; if (sk->sk_flags & flags) { sk->sk_flags &= ~flags; if (sock_needs_netstamp(sk) && !(sk->sk_flags & SK_FLAGS_TIMESTAMP)) net_disable_timestamp(); sock_set_flag(sk, flag); if (sock_needs_netstamp(sk) && !(previous_flags & SK_FLAGS_TIMESTAMP)) net_enable_timestamp(); /* Here, net_enable_timestamp() is not called because * previous_flags has the SOCK_TIMESTAMPING_RX_SOFTWARE * flag */ /* After the race, sk->sk has the flag SOCK_TIMESTAMP, but * net_enable_timestamp() is not called one more time. * Consequently, when the socket is closed, __sk_destruct() * calls net_disable_timestamp() that leads WARNING. */ Call Sequence: CPU0 = sock_setsockopt (SO_TIMESTAMPING) sock_disable_timestamp CPU1 = inet_ioctl (SIOCGSTAMPNS) sock_get_timestampns sock_enable_timestamp == [ cut here ] WARNING: CPU: 1 PID: 14465 at /home/blee/project/race-fuzzer/kernels/kernel_v4.8/kernel/jump_label.c:151 __static_key_slow_dec+0xc7/0xd0 kernel/jump_label.c:150 jump label: negative count! Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 14465 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 8801f2f5f608 81694cc3 82445d20 8801f2f5f6e0 82498700 8801f2f5f6e0 8801f2f5f6d0 812534a0 41b58ab3 829cae04 81253336 Call Trace: [] __dump_stack lib/dump_stack.c:15 [inline] [] dump_stack+0xb3/0x110 lib/dump_stack.c:51 [] panic+0x16a/0x336 kernel/panic.c:153 [] __warn+0x164/0x170 kernel/panic.c:509 [] warn_slowpath_fmt+0xac/0xd0 kernel/panic.c:532 [] __static_key_slow_dec+0xc7/0xd0 kernel/jump_label.c:150 [] static_key_slow_dec+0x33/0x60 kernel/jump_label.c:174 [] net_disable_timestamp+0x3b/0x50 net/core/dev.c:1729 [] sock_disable_timestamp+0x6e/0x80 net/core/sock.c:403 [] __sk_destruct+0xd4/0x260 net/core/sock.c:1453 [] sk_destruct+0x32/0x60 net/core/sock.c:1472 [] __sk_free+0x72/0x140 net/core/sock.c:1480 [] sk_free+0x23/0x30 net/core/sock.c:1491 [] sock_put include/net/sock.h:1582 [inline] [] sk_common_release+0x1ac/0x250 net/core/sock.c:2766 [] raw_close+0x21/0x30 net/ipv4/raw.c:687 [] inet_release+0x80/0xd0 net/ipv4/af_inet.c:420 [] sock_release+0x4e/0xf0 net/socket.c:573 [] sock_close+0x16/0x20 net/socket.c:1020 [] __fput+0x182/0x380 fs/file_table.c:208 [] fput+0x15/0x20 fs/file_table.c:244 [] task_work_run+0xcb/0x100 kernel/task_work.c:116 [] exit_task_work include/linux/task_work.h:21 [inline] [] do_exit+0x5a1/0x17f0 kernel/exit.c:828 [] do_group_exit+0xa7/0x190 kernel/exit.c:953 [] get_signal+0x465/0xdf0 kernel/signal.c:2307 [] do_signal+0x93/0xad0 arch/x86/kernel/signal.c:805 [] exit_to_usermode_loop+0xe0/0x110 arch/x86/entry/common.c:163 [] prepare_exit_to_usermode arch/x86/entry/common.c:198 [inline] [] syscall_return_slowpath+0x146/0x150 arch/x86/entry/common.c:267 [] entry_SYSCALL_64_fastpath+0xbb/0xbd Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: disabled == = About RaceFuzzer RaceFuzzer is a customized version
KASAN: use-after-free Read in vhost_chr_write_iter
We report the crash: KASAN: use-after-free Read in vhost_chr_write_iter This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$vnet and ioctl$VHOST_RESET_OWNER. Analysis: We think the concurrent execution of vhost_process_iotlb_msg() and vhost_dev_cleanup() causes the crash. Both of functions can run concurrently (please see call sequence below), and possibly, there is a race on dev->iotlb. If the switch occurs right after vhost_dev_cleanup() frees dev->iotlb, vhost_process_iotlb_msg() still sees the non-null value and it keep executing without returning -EFAULT. Consequently, use-after-free occures Thread interleaving: CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) (In the case of both VHOST_IOTLB_UPDATE and VHOST_IOTLB_INVALIDATE) = = vhost_umem_clean(dev->iotlb); if (!dev->iotlb) { ret = -EFAULT; break; } dev->iotlb = NULL; Call Sequence: CPU0 = vhost_net_chr_write_iter vhost_chr_write_iter vhost_process_iotlb_msg CPU1 = vhost_net_ioctl vhost_net_reset_owner vhost_dev_reset_owner vhost_dev_cleanup == BUG: KASAN: use-after-free in vhost_umem_interval_tree_iter_first drivers/vhost/vhost.c:52 [inline] BUG: KASAN: use-after-free in vhost_del_umem_range drivers/vhost/vhost.c:936 [inline] BUG: KASAN: use-after-free in vhost_process_iotlb_msg drivers/vhost/vhost.c:1010 [inline] BUG: KASAN: use-after-free in vhost_chr_write_iter+0x44e/0xcd0 drivers/vhost/vhost.c:1037 Read of size 8 at addr 8801d9d7bc00 by task syz-executor0/4997 CPU: 0 PID: 4997 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 vhost_umem_interval_tree_iter_first drivers/vhost/vhost.c:52 [inline] vhost_del_umem_range drivers/vhost/vhost.c:936 [inline] vhost_process_iotlb_msg drivers/vhost/vhost.c:1010 [inline] vhost_chr_write_iter+0x44e/0xcd0 drivers/vhost/vhost.c:1037 vhost_net_chr_write_iter+0x38/0x40 drivers/vhost/net.c:1380 call_write_iter include/linux/fs.h:1784 [inline] new_sync_write fs/read_write.c:474 [inline] __vfs_write+0x355/0x480 fs/read_write.c:487 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f4da7ce9b28 EFLAGS: 0246 ORIG_RAX: 0001 RAX: ffda RBX: 0072bee0 RCX: 004563f9 RDX: 0068 RSI: 26c0 RDI: 0015 RBP: 0729 R08: R09: R10: R11: 0246 R12: 7f4da7cea6d4 R13: R14: 006ffc78 R15: Allocated by task 4997: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553 __do_kmalloc_node mm/slab.c:3682 [inline] __kmalloc_node+0x47/0x70 mm/slab.c:3689 kmalloc_node include/linux/slab.h:554 [inline] kvmalloc_node+0x99/0xd0 mm/util.c:421 kvmalloc include/linux/mm.h:550 [inline] kvzalloc include/linux/mm.h:558 [inline] vhost_umem_alloc+0x72/0x120 drivers/vhost/vhost.c:1260 vhost_init_device_iotlb+0x1e/0x160 drivers/vhost/vhost.c:1548 vhost_net_set_features drivers/vhost/net.c:1273 [inline] vhost_net_ioctl+0x849/0x1040 drivers/vhost/net.c:1338 vfs_ioctl fs/ioctl.c:46 [inline] do_vfs_ioctl+0x145/0xd00 fs/ioctl.c:686 ksys_ioctl+0x94/0xb0 fs/ioctl.c:701 __do_sys_ioctl fs/ioctl.c:708 [inline] __se_sys_ioctl fs/ioctl.c:706 [inline] __x64_sys_ioctl+0x43/0x50 fs/ioctl.c:706 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 5000: 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] kfree+0xd9/0x260
KASAN: use-after-free Read in vhost_chr_write_iter
We report the crash: KASAN: use-after-free Read in vhost_chr_write_iter This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$vnet and ioctl$VHOST_RESET_OWNER. Analysis: We think the concurrent execution of vhost_process_iotlb_msg() and vhost_dev_cleanup() causes the crash. Both of functions can run concurrently (please see call sequence below), and possibly, there is a race on dev->iotlb. If the switch occurs right after vhost_dev_cleanup() frees dev->iotlb, vhost_process_iotlb_msg() still sees the non-null value and it keep executing without returning -EFAULT. Consequently, use-after-free occures Thread interleaving: CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) (In the case of both VHOST_IOTLB_UPDATE and VHOST_IOTLB_INVALIDATE) = = vhost_umem_clean(dev->iotlb); if (!dev->iotlb) { ret = -EFAULT; break; } dev->iotlb = NULL; Call Sequence: CPU0 = vhost_net_chr_write_iter vhost_chr_write_iter vhost_process_iotlb_msg CPU1 = vhost_net_ioctl vhost_net_reset_owner vhost_dev_reset_owner vhost_dev_cleanup == BUG: KASAN: use-after-free in vhost_umem_interval_tree_iter_first drivers/vhost/vhost.c:52 [inline] BUG: KASAN: use-after-free in vhost_del_umem_range drivers/vhost/vhost.c:936 [inline] BUG: KASAN: use-after-free in vhost_process_iotlb_msg drivers/vhost/vhost.c:1010 [inline] BUG: KASAN: use-after-free in vhost_chr_write_iter+0x44e/0xcd0 drivers/vhost/vhost.c:1037 Read of size 8 at addr 8801d9d7bc00 by task syz-executor0/4997 CPU: 0 PID: 4997 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 vhost_umem_interval_tree_iter_first drivers/vhost/vhost.c:52 [inline] vhost_del_umem_range drivers/vhost/vhost.c:936 [inline] vhost_process_iotlb_msg drivers/vhost/vhost.c:1010 [inline] vhost_chr_write_iter+0x44e/0xcd0 drivers/vhost/vhost.c:1037 vhost_net_chr_write_iter+0x38/0x40 drivers/vhost/net.c:1380 call_write_iter include/linux/fs.h:1784 [inline] new_sync_write fs/read_write.c:474 [inline] __vfs_write+0x355/0x480 fs/read_write.c:487 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f4da7ce9b28 EFLAGS: 0246 ORIG_RAX: 0001 RAX: ffda RBX: 0072bee0 RCX: 004563f9 RDX: 0068 RSI: 26c0 RDI: 0015 RBP: 0729 R08: R09: R10: R11: 0246 R12: 7f4da7cea6d4 R13: R14: 006ffc78 R15: Allocated by task 4997: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553 __do_kmalloc_node mm/slab.c:3682 [inline] __kmalloc_node+0x47/0x70 mm/slab.c:3689 kmalloc_node include/linux/slab.h:554 [inline] kvmalloc_node+0x99/0xd0 mm/util.c:421 kvmalloc include/linux/mm.h:550 [inline] kvzalloc include/linux/mm.h:558 [inline] vhost_umem_alloc+0x72/0x120 drivers/vhost/vhost.c:1260 vhost_init_device_iotlb+0x1e/0x160 drivers/vhost/vhost.c:1548 vhost_net_set_features drivers/vhost/net.c:1273 [inline] vhost_net_ioctl+0x849/0x1040 drivers/vhost/net.c:1338 vfs_ioctl fs/ioctl.c:46 [inline] do_vfs_ioctl+0x145/0xd00 fs/ioctl.c:686 ksys_ioctl+0x94/0xb0 fs/ioctl.c:701 __do_sys_ioctl fs/ioctl.c:708 [inline] __se_sys_ioctl fs/ioctl.c:706 [inline] __x64_sys_ioctl+0x43/0x50 fs/ioctl.c:706 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 5000: 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] kfree+0xd9/0x260
KASAN: null-ptr-deref Read in rdma_listen
We report the crash: KASAN: null-ptr-deref Read in rdma_listen This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two write syscalls with the command 'listen' concurrently . Diagnosis: We think two concurrent execution of rdma_listen() causes the problem. Scenario is as follows. One thread executes rdma_listen(). and then it enters rdma_bind_addr() because id_priv->state is RDMA_CM_IDLE at the beginning. it changes the value of id_priv->state to RDMA_CM_ADDR_BOUND. And then switch to the other thread. This thread also runs rdma_listen(). Since the first thread changes the value of id_priv->state to the RDMA_CM_ADDR_BOUND, the second thread can change the value of id_priv->state to the RDMA_CM_LISTEN and can executes cma_bind_listen(). But since the first thread has not finished the rdma_bind_addr(), id_priv->bind_list is still null. Therefore, null-ptr-deref occurs in cma_bind_listen(). Thread interleaving: CPU0 (rdma_listen) CPU1 (rdma_listen) = = id_priv = container_of(id, struct rdma_id_private, id); if (id_priv->state == RDMA_CM_IDLE) { id->route.addr.src_addr.ss_family = AF_INET; ret = rdma_bind_addr(id, cma_src_addr(id_priv)); ... (in rdma_bind_addr) id_priv = container_of(id, struct rdma_id_private, id); if (!cma_comp_exch(id_priv, RDMA_CM_IDLE, RDMA_CM_ADDR_BOUND)) id_priv = container_of(id, struct rdma_id_private, id); // Here, id_priv->state is already RDMA_CM_ADDR_BOUND if (id_priv->state == RDMA_CM_IDLE) { ... } if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) return -EINVAL; if (id_priv->reuseaddr) { ret = cma_bind_listen(id_priv); ... ret = cma_get_port(id_priv); Call sequence (v4.17-rc1): CPU0 ucma_listen rdma_listen rdma_bind_addr CPU1 ucma_listen rdma_listen cma_bind_listen Crash log: == BUG: KASAN: null-ptr-deref in cma_bind_listen drivers/infiniband/core/cma.c:3167 [inline] BUG: KASAN: null-ptr-deref in rdma_listen+0x1f6/0x4f0 drivers/infiniband/core/cma.c:3281 Read of size 8 at addr 0008 by task syz-executor0/21413 CPU: 1 PID: 21413 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report+0x140/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 cma_bind_listen drivers/infiniband/core/cma.c:3167 [inline] rdma_listen+0x1f6/0x4f0 drivers/infiniband/core/cma.c:3281 ucma_listen+0xeb/0x150 drivers/infiniband/core/ucma.c:1079 ucma_write+0x1d6/0x260 drivers/infiniband/core/ucma.c:1664 __vfs_write+0xdd/0x480 fs/read_write.c:485 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7fb1d41c6b28 EFLAGS: 0246 ORIG_RAX: 0001 RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 0010 RSI: 2140 RDI: 0016 RBP: 0720 R08: R09: R10: R11: 0246 R12: 7fb1d41c76d4 R13: R14: 006ffba0 R15: == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting
KASAN: null-ptr-deref Read in rdma_listen
We report the crash: KASAN: null-ptr-deref Read in rdma_listen This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two write syscalls with the command 'listen' concurrently . Diagnosis: We think two concurrent execution of rdma_listen() causes the problem. Scenario is as follows. One thread executes rdma_listen(). and then it enters rdma_bind_addr() because id_priv->state is RDMA_CM_IDLE at the beginning. it changes the value of id_priv->state to RDMA_CM_ADDR_BOUND. And then switch to the other thread. This thread also runs rdma_listen(). Since the first thread changes the value of id_priv->state to the RDMA_CM_ADDR_BOUND, the second thread can change the value of id_priv->state to the RDMA_CM_LISTEN and can executes cma_bind_listen(). But since the first thread has not finished the rdma_bind_addr(), id_priv->bind_list is still null. Therefore, null-ptr-deref occurs in cma_bind_listen(). Thread interleaving: CPU0 (rdma_listen) CPU1 (rdma_listen) = = id_priv = container_of(id, struct rdma_id_private, id); if (id_priv->state == RDMA_CM_IDLE) { id->route.addr.src_addr.ss_family = AF_INET; ret = rdma_bind_addr(id, cma_src_addr(id_priv)); ... (in rdma_bind_addr) id_priv = container_of(id, struct rdma_id_private, id); if (!cma_comp_exch(id_priv, RDMA_CM_IDLE, RDMA_CM_ADDR_BOUND)) id_priv = container_of(id, struct rdma_id_private, id); // Here, id_priv->state is already RDMA_CM_ADDR_BOUND if (id_priv->state == RDMA_CM_IDLE) { ... } if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) return -EINVAL; if (id_priv->reuseaddr) { ret = cma_bind_listen(id_priv); ... ret = cma_get_port(id_priv); Call sequence (v4.17-rc1): CPU0 ucma_listen rdma_listen rdma_bind_addr CPU1 ucma_listen rdma_listen cma_bind_listen Crash log: == BUG: KASAN: null-ptr-deref in cma_bind_listen drivers/infiniband/core/cma.c:3167 [inline] BUG: KASAN: null-ptr-deref in rdma_listen+0x1f6/0x4f0 drivers/infiniband/core/cma.c:3281 Read of size 8 at addr 0008 by task syz-executor0/21413 CPU: 1 PID: 21413 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report+0x140/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 cma_bind_listen drivers/infiniband/core/cma.c:3167 [inline] rdma_listen+0x1f6/0x4f0 drivers/infiniband/core/cma.c:3281 ucma_listen+0xeb/0x150 drivers/infiniband/core/ucma.c:1079 ucma_write+0x1d6/0x260 drivers/infiniband/core/ucma.c:1664 __vfs_write+0xdd/0x480 fs/read_write.c:485 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7fb1d41c6b28 EFLAGS: 0246 ORIG_RAX: 0001 RAX: ffda RBX: 0072bfa0 RCX: 004563f9 RDX: 0010 RSI: 2140 RDI: 0016 RBP: 0720 R08: R09: R10: R11: 0246 R12: 7fb1d41c76d4 R13: R14: 006ffba0 R15: == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting
Re: KASAN: use-after-free Read in cma_cancel_operation
On Sun, May 13, 2018 at 02:34:13PM -0600, Jason Gunthorpe wrote: > On Fri, May 11, 2018 at 02:25:22PM +0900, DaeRyong Jeong wrote: > > We report the crash: KASAN: use-after-free Read in cma_cancel_operation > > > > Note that this bug is previously reported by syzkaller. > > https://syzkaller.appspot.com/bug?id=95f89b8fb9fdc42e28ad586e657fea074e4e719b > > Nonetheless, this bug has not fixed yet, and we hope that this report and > > our > > analysis, which gets help by the RaceFuzzer's feature, will helpful to fix > > the > > crash. > > > > This crash has been found in v4.17-rc1 using RaceFuzzer (a modified > > version of Syzkaller), which we describe more at the end of this > > report. Our analysis shows that the race occurs when invoking two > > syscalls concurrently, write$rdma_cm and write$rdma_cm. > > Well, calling rdma_destroy_id() twice/concurrently is invalid.. The > confusing part of this is how does it happen from ucma.c .. > > Double calls via write look OK to me, the ID is removed from the IDR > at the top so it cannot be invoked twice.. So not sure what > "write$rdma_cm and write$rdma_cm." is supposed to me? It meant two write syscalls. One for ucma_listen, one for ucma_resolve_ip. > > Is your test showing that write() vs close() is the problem? The oops > suggests that.. And the logic around ctx->closing looks tortured > enough that it is probably wrong... My previous dianosis seems wrong... I'm sorry to make you confusing. I'm looking into the code and trying to find out the cause of the crash. > > Jason We have found the one more crash. null-ptr-deref in cma_bind_listen caused by two ucma_listen calls. I think I have the clear idea why null-ptr-deref occured. I will send the report for the null-ptr-deref. Please look at it. We suspect that this crash and null-ptr-deref have the same root cause, incomplete state check. Hopefully, the second report is helpful to find out the root cause of this bug. DaeRyong Jeong
Re: KASAN: use-after-free Read in cma_cancel_operation
On Sun, May 13, 2018 at 02:34:13PM -0600, Jason Gunthorpe wrote: > On Fri, May 11, 2018 at 02:25:22PM +0900, DaeRyong Jeong wrote: > > We report the crash: KASAN: use-after-free Read in cma_cancel_operation > > > > Note that this bug is previously reported by syzkaller. > > https://syzkaller.appspot.com/bug?id=95f89b8fb9fdc42e28ad586e657fea074e4e719b > > Nonetheless, this bug has not fixed yet, and we hope that this report and > > our > > analysis, which gets help by the RaceFuzzer's feature, will helpful to fix > > the > > crash. > > > > This crash has been found in v4.17-rc1 using RaceFuzzer (a modified > > version of Syzkaller), which we describe more at the end of this > > report. Our analysis shows that the race occurs when invoking two > > syscalls concurrently, write$rdma_cm and write$rdma_cm. > > Well, calling rdma_destroy_id() twice/concurrently is invalid.. The > confusing part of this is how does it happen from ucma.c .. > > Double calls via write look OK to me, the ID is removed from the IDR > at the top so it cannot be invoked twice.. So not sure what > "write$rdma_cm and write$rdma_cm." is supposed to me? It meant two write syscalls. One for ucma_listen, one for ucma_resolve_ip. > > Is your test showing that write() vs close() is the problem? The oops > suggests that.. And the logic around ctx->closing looks tortured > enough that it is probably wrong... My previous dianosis seems wrong... I'm sorry to make you confusing. I'm looking into the code and trying to find out the cause of the crash. > > Jason We have found the one more crash. null-ptr-deref in cma_bind_listen caused by two ucma_listen calls. I think I have the clear idea why null-ptr-deref occured. I will send the report for the null-ptr-deref. Please look at it. We suspect that this crash and null-ptr-deref have the same root cause, incomplete state check. Hopefully, the second report is helpful to find out the root cause of this bug. DaeRyong Jeong
KASAN: use-after-free Read in cma_cancel_operation
We report the crash: KASAN: use-after-free Read in cma_cancel_operation Note that this bug is previously reported by syzkaller. https://syzkaller.appspot.com/bug?id=95f89b8fb9fdc42e28ad586e657fea074e4e719b Nonetheless, this bug has not fixed yet, and we hope that this report and our analysis, which gets help by the RaceFuzzer's feature, will helpful to fix the crash. This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$rdma_cm and write$rdma_cm. Analysis: We think the concurrent execution of rdma_destroy_id() causes the crash. The first execution of rdma_destroy_id() calls kfree(id_priv), and the second execution of rdma_destry_id() dereferences the id_priv in cma_cancel_listens(). Therefore use-after-free read occurs. We observed that rdma_destroy_id() is called during the write$rdma_cm syscall. After returing from vfs_write(), fput() is called and ucma_close() is called as a pending work before returing to the user space. Thread interleaving: CPU0 (rdma_destory_id) CPU1 (rdma_destroy_id) = = kfree(id_priv->id.route.path_rec); put_net(id_priv->id.route.addr.dev_addr.net); kfree(id_priv); id_priv = container_of(id, struct rdma_id_private, id); state = cma_exch(id_priv, RDMA_CM_DESTROYING); cma_cancel_operation(id_priv, state); (in cma_cancel_listens) list_del(_priv->list); Call Sequence: Both CPU0 and CPU1 = ucma_close rdma_destroy_id == BUG: KASAN: use-after-free in __list_del_entry_valid+0x5c/0xc0 lib/list_debug.c:54 Read of size 8 at addr 8801e86deca0 by task syz-executor0/3524 CPU: 1 PID: 3524 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 __list_del_entry_valid+0x5c/0xc0 lib/list_debug.c:54 __list_del_entry include/linux/list.h:117 [inline] list_del include/linux/list.h:125 [inline] cma_cancel_listens drivers/infiniband/core/cma.c:1527 [inline] cma_cancel_operation+0x2d2/0x750 drivers/infiniband/core/cma.c:1555 rdma_destroy_id+0xe9/0x760 drivers/infiniband/core/cma.c:1619 ucma_close+0x9f/0x1c0 drivers/infiniband/core/ucma.c:1743 __fput+0x22c/0x450 fs/file_table.c:209 fput+0x15/0x20 fs/file_table.c:243 task_work_run+0x152/0x1b0 kernel/task_work.c:113 exit_task_work include/linux/task_work.h:22 [inline] do_exit+0x1387/0x1860 kernel/exit.c:865 do_group_exit+0xfb/0x220 kernel/exit.c:968 get_signal+0x5b7/0xf70 kernel/signal.c:2469 do_signal+0x94/0xde0 arch/x86/kernel/signal.c:810 exit_to_usermode_loop+0x1eb/0x270 arch/x86/entry/common.c:162 prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline] syscall_return_slowpath arch/x86/entry/common.c:265 [inline] do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7fdd885d9ba8 EFLAGS: 0246 ORIG_RAX: 00ca RAX: fe00 RBX: 0072bfc8 RCX: 004563f9 RDX: RSI: RDI: 0072bfc8 RBP: 7fdd885d9bd0 R08: R09: 0072bfa0 R10: R11: 0246 R12: 0001 R13: 7fdd885d9c50 R14: R15: 7fdd885da700 Allocated by task 3521: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553 kmem_cache_alloc_trace+0x136/0x740 mm/slab.c:3620 kmalloc include/linux/slab.h:512 [inline] kzalloc include/linux/slab.h:701 [inline] __rdma_create_id+0xc5/0x450 drivers/infiniband/core/cma.c:751 ucma_create_id+0x219/0x510 drivers/infiniband/core/ucma.c:485 ucma_write+0x1d6/0x260 drivers/infiniband/core/ucma.c:1664 __vfs_write+0xdd/0x480 fs/read_write.c:485 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
KASAN: use-after-free Read in cma_cancel_operation
We report the crash: KASAN: use-after-free Read in cma_cancel_operation Note that this bug is previously reported by syzkaller. https://syzkaller.appspot.com/bug?id=95f89b8fb9fdc42e28ad586e657fea074e4e719b Nonetheless, this bug has not fixed yet, and we hope that this report and our analysis, which gets help by the RaceFuzzer's feature, will helpful to fix the crash. This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$rdma_cm and write$rdma_cm. Analysis: We think the concurrent execution of rdma_destroy_id() causes the crash. The first execution of rdma_destroy_id() calls kfree(id_priv), and the second execution of rdma_destry_id() dereferences the id_priv in cma_cancel_listens(). Therefore use-after-free read occurs. We observed that rdma_destroy_id() is called during the write$rdma_cm syscall. After returing from vfs_write(), fput() is called and ucma_close() is called as a pending work before returing to the user space. Thread interleaving: CPU0 (rdma_destory_id) CPU1 (rdma_destroy_id) = = kfree(id_priv->id.route.path_rec); put_net(id_priv->id.route.addr.dev_addr.net); kfree(id_priv); id_priv = container_of(id, struct rdma_id_private, id); state = cma_exch(id_priv, RDMA_CM_DESTROYING); cma_cancel_operation(id_priv, state); (in cma_cancel_listens) list_del(_priv->list); Call Sequence: Both CPU0 and CPU1 = ucma_close rdma_destroy_id == BUG: KASAN: use-after-free in __list_del_entry_valid+0x5c/0xc0 lib/list_debug.c:54 Read of size 8 at addr 8801e86deca0 by task syz-executor0/3524 CPU: 1 PID: 3524 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 print_address_description+0x73/0x250 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x23f/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 __list_del_entry_valid+0x5c/0xc0 lib/list_debug.c:54 __list_del_entry include/linux/list.h:117 [inline] list_del include/linux/list.h:125 [inline] cma_cancel_listens drivers/infiniband/core/cma.c:1527 [inline] cma_cancel_operation+0x2d2/0x750 drivers/infiniband/core/cma.c:1555 rdma_destroy_id+0xe9/0x760 drivers/infiniband/core/cma.c:1619 ucma_close+0x9f/0x1c0 drivers/infiniband/core/ucma.c:1743 __fput+0x22c/0x450 fs/file_table.c:209 fput+0x15/0x20 fs/file_table.c:243 task_work_run+0x152/0x1b0 kernel/task_work.c:113 exit_task_work include/linux/task_work.h:22 [inline] do_exit+0x1387/0x1860 kernel/exit.c:865 do_group_exit+0xfb/0x220 kernel/exit.c:968 get_signal+0x5b7/0xf70 kernel/signal.c:2469 do_signal+0x94/0xde0 arch/x86/kernel/signal.c:810 exit_to_usermode_loop+0x1eb/0x270 arch/x86/entry/common.c:162 prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline] syscall_return_slowpath arch/x86/entry/common.c:265 [inline] do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7fdd885d9ba8 EFLAGS: 0246 ORIG_RAX: 00ca RAX: fe00 RBX: 0072bfc8 RCX: 004563f9 RDX: RSI: RDI: 0072bfc8 RBP: 7fdd885d9bd0 R08: R09: 0072bfa0 R10: R11: 0246 R12: 0001 R13: 7fdd885d9c50 R14: R15: 7fdd885da700 Allocated by task 3521: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553 kmem_cache_alloc_trace+0x136/0x740 mm/slab.c:3620 kmalloc include/linux/slab.h:512 [inline] kzalloc include/linux/slab.h:701 [inline] __rdma_create_id+0xc5/0x450 drivers/infiniband/core/cma.c:751 ucma_create_id+0x219/0x510 drivers/infiniband/core/ucma.c:485 ucma_write+0x1d6/0x260 drivers/infiniband/core/ucma.c:1664 __vfs_write+0xdd/0x480 fs/read_write.c:485 vfs_write+0x12d/0x2d0 fs/read_write.c:549 ksys_write+0xca/0x190 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+0x43/0x50 fs/read_write.c:607 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
KASAN: null-ptr-deref Read in rds_ib_get_mr
We report the crash: KASAN: null-ptr-deref Read in rds_ib_get_mr Note that this bug is previously reported by syzkaller. https://syzkaller.appspot.com/bug?id=0bb56a5a48b000b52aa2b0d8dd20b1f545214d91 Nonetheless, this bug has not fixed yet, and we hope that this report and our analysis, which gets help by the RaceFuzzer's feature, will helpful to fix the crash. This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, bind$rds and setsockopt$RDS_GET_MR. Analysis: We think the concurrent execution of __rds_rdma_map() and rds_bind() causes the problem. __rds_rdma_map() checks whether rs->rs_bound_addr is 0 or not. But the concurrent execution with rds_bind() can by-pass this check. Therefore, __rds_rdmap_map() calls rs->rs_transport->get_mr() and rds_ib_get_mr() causes the null deref at ib_rdma.c:544 in v4.17-rc1, when dereferencing rs_conn. Thread interleaving: CPU0 (__rds_rdma_map) CPU1 (rds_bind) // rds_add_bound() sets rs->bound_addr as none 0 ret = rds_add_bound(rs, sin->sin_addr.s_addr, >sin_port); if (rs->rs_bound_addr == 0 || !rs->rs_transport) { ret = -ENOTCONN; /* XXX not a great errno */ goto out; } if (rs->rs_transport) { /* previously bound */ trans = rs->rs_transport; if (trans->laddr_check(sock_net(sock->sk), sin->sin_addr.s_addr) != 0) { ret = -ENOPROTOOPT; // rds_remove_bound() sets rs->bound_addr as 0 rds_remove_bound(rs); ... trans_private = rs->rs_transport->get_mr(sg, nents, rs, >r_key); (in rds_ib_get_mr()) struct rds_ib_connection *ic = rs->rs_conn->c_transport_data; Call sequence (v4.17-rc1): CPU0 rds_setsockopt rds_get_mr __rds_rdma_map rds_ib_get_mr CPU1 rds_bind rds_add_bound ... rds_remove_bound Crash log: == BUG: KASAN: null-ptr-deref in rds_ib_get_mr+0x3a/0x150 net/rds/ib_rdma.c:544 Read of size 8 at addr 0068 by task syz-executor0/32067 CPU: 0 PID: 32067 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report+0x140/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 rds_ib_get_mr+0x3a/0x150 net/rds/ib_rdma.c:544 __rds_rdma_map+0x521/0x9d0 net/rds/rdma.c:271 rds_get_mr+0xad/0xf0 net/rds/rdma.c:333 rds_setsockopt+0x57f/0x720 net/rds/af_rds.c:347 __sys_setsockopt+0x147/0x230 net/socket.c:1903 __do_sys_setsockopt net/socket.c:1914 [inline] __se_sys_setsockopt net/socket.c:1911 [inline] __x64_sys_setsockopt+0x67/0x80 net/socket.c:1911 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f6a2b3c2b28 EFLAGS: 0246 ORIG_RAX: 0036 RAX: ffda RBX: 0072bee0 RCX: 004563f9 RDX: 0002 RSI: 0114 RDI: 0015 RBP: 0575 R08: 0020 R09: R10: 2140 R11: 0246 R12: 7f6a2b3c36d4 R13: R14: 006fd398 R15: == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the
KASAN: null-ptr-deref Read in rds_ib_get_mr
We report the crash: KASAN: null-ptr-deref Read in rds_ib_get_mr Note that this bug is previously reported by syzkaller. https://syzkaller.appspot.com/bug?id=0bb56a5a48b000b52aa2b0d8dd20b1f545214d91 Nonetheless, this bug has not fixed yet, and we hope that this report and our analysis, which gets help by the RaceFuzzer's feature, will helpful to fix the crash. This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, bind$rds and setsockopt$RDS_GET_MR. Analysis: We think the concurrent execution of __rds_rdma_map() and rds_bind() causes the problem. __rds_rdma_map() checks whether rs->rs_bound_addr is 0 or not. But the concurrent execution with rds_bind() can by-pass this check. Therefore, __rds_rdmap_map() calls rs->rs_transport->get_mr() and rds_ib_get_mr() causes the null deref at ib_rdma.c:544 in v4.17-rc1, when dereferencing rs_conn. Thread interleaving: CPU0 (__rds_rdma_map) CPU1 (rds_bind) // rds_add_bound() sets rs->bound_addr as none 0 ret = rds_add_bound(rs, sin->sin_addr.s_addr, >sin_port); if (rs->rs_bound_addr == 0 || !rs->rs_transport) { ret = -ENOTCONN; /* XXX not a great errno */ goto out; } if (rs->rs_transport) { /* previously bound */ trans = rs->rs_transport; if (trans->laddr_check(sock_net(sock->sk), sin->sin_addr.s_addr) != 0) { ret = -ENOPROTOOPT; // rds_remove_bound() sets rs->bound_addr as 0 rds_remove_bound(rs); ... trans_private = rs->rs_transport->get_mr(sg, nents, rs, >r_key); (in rds_ib_get_mr()) struct rds_ib_connection *ic = rs->rs_conn->c_transport_data; Call sequence (v4.17-rc1): CPU0 rds_setsockopt rds_get_mr __rds_rdma_map rds_ib_get_mr CPU1 rds_bind rds_add_bound ... rds_remove_bound Crash log: == BUG: KASAN: null-ptr-deref in rds_ib_get_mr+0x3a/0x150 net/rds/ib_rdma.c:544 Read of size 8 at addr 0068 by task syz-executor0/32067 CPU: 0 PID: 32067 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x166/0x21c lib/dump_stack.c:113 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report+0x140/0x360 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load8+0x54/0x90 mm/kasan/kasan.c:699 rds_ib_get_mr+0x3a/0x150 net/rds/ib_rdma.c:544 __rds_rdma_map+0x521/0x9d0 net/rds/rdma.c:271 rds_get_mr+0xad/0xf0 net/rds/rdma.c:333 rds_setsockopt+0x57f/0x720 net/rds/af_rds.c:347 __sys_setsockopt+0x147/0x230 net/socket.c:1903 __do_sys_setsockopt net/socket.c:1914 [inline] __se_sys_setsockopt net/socket.c:1911 [inline] __x64_sys_setsockopt+0x67/0x80 net/socket.c:1911 do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4563f9 RSP: 002b:7f6a2b3c2b28 EFLAGS: 0246 ORIG_RAX: 0036 RAX: ffda RBX: 0072bee0 RCX: 004563f9 RDX: 0002 RSI: 0114 RDI: 0015 RBP: 0575 R08: 0020 R09: R10: 2140 R11: 0246 R12: 7f6a2b3c36d4 R13: R14: 006fd398 R15: == = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the
[PATCH v2] tty: Fix data race in tty_insert_flip_string_fixed_flag
Unlike normal serials, in pty layer, there is no guarantee that multiple threads don't insert input characters at the same time. If it is happened, tty_insert_flip_string_fixed_flag can be executed concurrently. This can lead slab out-of-bounds write in tty_insert_flip_string_fixed_flag. Call sequences are as follows. CPU0CPU1 n_tty_ioctl_helper n_tty_ioctl_helper __start_tty tty_send_xchar tty_wakeup pty_write n_hdlc_tty_wakeup tty_insert_flip_string n_hdlc_send_frames tty_insert_flip_string_fixed_flag pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag To fix the race, acquire port->lock in pty_write() before it inserts input characters to tty buffer. It prevents multiple threads from inserting input characters concurrently. The crash log is as follows: BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 Write of size 1792 by task syz-executor0/30017 CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 88011638f888 81694cc3 88007d802140 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 8130075c 88011638f940 88007d802140 880194fcc121 Call Trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xb3/0x110 lib/dump_stack.c:51 kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 print_address_description mm/kasan/report.c:194 [inline] kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 kasan_report+0x36/0x40 mm/kasan/report.c:303 check_memory_region_inline mm/kasan/kasan.c:292 [inline] check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 memcpy+0x37/0x50 mm/kasan/kasan.c:335 tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 tty_insert_flip_string include/linux/tty_flip.h:35 [inline] pty_write+0x7f/0xc0 drivers/tty/pty.c:115 n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 vfs_ioctl fs/ioctl.c:43 [inline] do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 SYSC_ioctl fs/ioctl.c:694 [inline] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 entry_SYSCALL_64_fastpath+0x1f/0xbd Signed-off-by: DaeRyong Jeong <threeear...@gmail.com> --- drivers/tty/pty.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 364c0e9..0c7ec27 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -110,16 +110,19 @@ static void pty_unthrottle(struct tty_struct *tty) static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) { struct tty_struct *to = tty->link; + unsigned long flags; if (tty->stopped) return 0; if (c > 0) { + spin_lock_irqsave(>port->lock, flags); /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to->port, buf, c); /* And shovel */ if (c) tty_flip_buffer_push(to->port); + spin_unlock_irqrestore(>port->lock, flags); } return c; } -- 2.7.4
[PATCH v2] tty: Fix data race in tty_insert_flip_string_fixed_flag
Unlike normal serials, in pty layer, there is no guarantee that multiple threads don't insert input characters at the same time. If it is happened, tty_insert_flip_string_fixed_flag can be executed concurrently. This can lead slab out-of-bounds write in tty_insert_flip_string_fixed_flag. Call sequences are as follows. CPU0CPU1 n_tty_ioctl_helper n_tty_ioctl_helper __start_tty tty_send_xchar tty_wakeup pty_write n_hdlc_tty_wakeup tty_insert_flip_string n_hdlc_send_frames tty_insert_flip_string_fixed_flag pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag To fix the race, acquire port->lock in pty_write() before it inserts input characters to tty buffer. It prevents multiple threads from inserting input characters concurrently. The crash log is as follows: BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 Write of size 1792 by task syz-executor0/30017 CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 88011638f888 81694cc3 88007d802140 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 8130075c 88011638f940 88007d802140 880194fcc121 Call Trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xb3/0x110 lib/dump_stack.c:51 kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 print_address_description mm/kasan/report.c:194 [inline] kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 kasan_report+0x36/0x40 mm/kasan/report.c:303 check_memory_region_inline mm/kasan/kasan.c:292 [inline] check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 memcpy+0x37/0x50 mm/kasan/kasan.c:335 tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 tty_insert_flip_string include/linux/tty_flip.h:35 [inline] pty_write+0x7f/0xc0 drivers/tty/pty.c:115 n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 vfs_ioctl fs/ioctl.c:43 [inline] do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 SYSC_ioctl fs/ioctl.c:694 [inline] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 entry_SYSCALL_64_fastpath+0x1f/0xbd Signed-off-by: DaeRyong Jeong --- drivers/tty/pty.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 364c0e9..0c7ec27 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -110,16 +110,19 @@ static void pty_unthrottle(struct tty_struct *tty) static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) { struct tty_struct *to = tty->link; + unsigned long flags; if (tty->stopped) return 0; if (c > 0) { + spin_lock_irqsave(>port->lock, flags); /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to->port, buf, c); /* And shovel */ if (c) tty_flip_buffer_push(to->port); + spin_unlock_irqrestore(>port->lock, flags); } return c; } -- 2.7.4
KASAN: use-after-free in loopback_active_get
We report the crash: KASAN: use-after-free in loopback_active_get This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, ioctl$SNDRV_CTL_IOCTL_ELEM_READ and syz_open_dev$audion. kernel config: https://kiwi.cs.purdue.ed/static/race-fuzzer/KASAN_use-after-free_in_loopback_active_get.config Analysis: When there is a race between sound/drivers/aloop.c:895 (loopback_active_get) and sound/drivers/aloop.c:678 (free_cable), the retrieved cable pointer in loopback_active_get() may point to the freed memory region. When loopback_active_get() dereferences this pointer, use-after-free occurs. Possible CPU execution: CPU0CPU1 loopback_active_get() free_cable() struct loopback_cable *cable = ... loopback->cables[substream->number][dev] = NULL; kfree(cable); cable->running <-- Use-after-free Call Sequence: CPU0 loopback_active_get snd_ctl_elem_read snd_ctl_elem_read_user snd_ctl_ioctl CPU1 free_cable loopback_close snd_pcm_release_substream snd_pcm_release_substream snd_pcm_oss_release_file snd_pcm_oss_release_file snd_pcm_oss_release We observed that snd_pcm_oss_release() is called during the open("/dev/audio1") syscall. In our configuration, the function do_dentry_open() returns -EINVAL since below if statement is evaluated as true. if ((f->f_flags & O_DIRECT) (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)) Therefore, fput() is called and snd_pcm_oss_release() is called as a pending work before returning to the user space. But we suspect that the insufficient locking between snd_ctl_ioctl() and snd_pcm_oss_release(), not the vfs_layer, is the cause of the crash. Read of size 4 at addr 88023aa4899c by task syz-executor0/27703 CPU: 0 PID: 27703 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x182/0x24c 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+0xac/0x2f5 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load4+0x78/0x80 mm/kasan/kasan.c:698 loopback_active_get+0x71/0xb0 sound/drivers/aloop.c:900 snd_ctl_elem_read+0x14e/0x190 sound/core/control.c:896 snd_ctl_elem_read_user sound/core/control.c:914 [inline] snd_ctl_ioctl+0xaf7/0xce0 sound/core/control.c:1560 vfs_ioctl fs/ioctl.c:46 [inline] file_ioctl fs/ioctl.c:500 [inline] do_vfs_ioctl+0x179/0xf40 fs/ioctl.c:684 ksys_ioctl+0xa9/0xd0 fs/ioctl.c:701 __do_sys_ioctl fs/ioctl.c:708 [inline] __se_sys_ioctl fs/ioctl.c:706 [inline] __x64_sys_ioctl+0x43/0x50 fs/ioctl.c:706 do_syscall_64+0x17a/0x530 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x453bc9 RSP: 002b:7fc5fba5eaf8 EFLAGS: 0212 ORIG_RAX: 0010 RAX: ffda RBX: 00708020 RCX: 00453bc9 RDX: 20003b38 RSI: c4c85512 RDI: 0005 RBP: 25a0 R08: R09: R10: R11: 0212 R12: 004aed78 R13: R14: 0005 R15: c4c85512 Allocated by task 27704: 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 kmem_cache_alloc_trace+0x152/0x780 mm/slab.c:3620 kmalloc include/linux/slab.h:512 [inline] kzalloc include/linux/slab.h:701 [inline] loopback_open+0x4d2/0x720 sound/drivers/aloop.c:704 snd_pcm_open_substream+0x174/0x250 sound/core/pcm_native.c:2391 snd_pcm_oss_open_file sound/core/oss/pcm_oss.c:2423 [inline] snd_pcm_oss_open+0x799/0xfc0 sound/core/oss/pcm_oss.c:2505 soundcore_open+0x2db/0x3e0 sound/sound_core.c:597 chrdev_open+0x1c6/0x450 fs/char_dev.c:417 do_dentry_open+0x520/0x7c0 fs/open.c:784 vfs_open+0xc5/0x120 fs/open.c:906 do_last fs/namei.c:3365 [inline] path_openat+0x1133/0x31a0 fs/namei.c:3501 do_filp_open+0x15a/0x1e0 fs/namei.c:3535 do_sys_open+0x464/0x540 fs/open.c:1093 __do_sys_open fs/open.c: [inline] __se_sys_open fs/open.c:1106 [inline] __x64_sys_open+0x4c/0x60 fs/open.c:1106 do_syscall_64+0x17a/0x530 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 27704: 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
KASAN: use-after-free in loopback_active_get
We report the crash: KASAN: use-after-free in loopback_active_get This crash has been found in v4.17-rc1 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, ioctl$SNDRV_CTL_IOCTL_ELEM_READ and syz_open_dev$audion. kernel config: https://kiwi.cs.purdue.ed/static/race-fuzzer/KASAN_use-after-free_in_loopback_active_get.config Analysis: When there is a race between sound/drivers/aloop.c:895 (loopback_active_get) and sound/drivers/aloop.c:678 (free_cable), the retrieved cable pointer in loopback_active_get() may point to the freed memory region. When loopback_active_get() dereferences this pointer, use-after-free occurs. Possible CPU execution: CPU0CPU1 loopback_active_get() free_cable() struct loopback_cable *cable = ... loopback->cables[substream->number][dev] = NULL; kfree(cable); cable->running <-- Use-after-free Call Sequence: CPU0 loopback_active_get snd_ctl_elem_read snd_ctl_elem_read_user snd_ctl_ioctl CPU1 free_cable loopback_close snd_pcm_release_substream snd_pcm_release_substream snd_pcm_oss_release_file snd_pcm_oss_release_file snd_pcm_oss_release We observed that snd_pcm_oss_release() is called during the open("/dev/audio1") syscall. In our configuration, the function do_dentry_open() returns -EINVAL since below if statement is evaluated as true. if ((f->f_flags & O_DIRECT) (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)) Therefore, fput() is called and snd_pcm_oss_release() is called as a pending work before returning to the user space. But we suspect that the insufficient locking between snd_ctl_ioctl() and snd_pcm_oss_release(), not the vfs_layer, is the cause of the crash. Read of size 4 at addr 88023aa4899c by task syz-executor0/27703 CPU: 0 PID: 27703 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x182/0x24c 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+0xac/0x2f5 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load4+0x78/0x80 mm/kasan/kasan.c:698 loopback_active_get+0x71/0xb0 sound/drivers/aloop.c:900 snd_ctl_elem_read+0x14e/0x190 sound/core/control.c:896 snd_ctl_elem_read_user sound/core/control.c:914 [inline] snd_ctl_ioctl+0xaf7/0xce0 sound/core/control.c:1560 vfs_ioctl fs/ioctl.c:46 [inline] file_ioctl fs/ioctl.c:500 [inline] do_vfs_ioctl+0x179/0xf40 fs/ioctl.c:684 ksys_ioctl+0xa9/0xd0 fs/ioctl.c:701 __do_sys_ioctl fs/ioctl.c:708 [inline] __se_sys_ioctl fs/ioctl.c:706 [inline] __x64_sys_ioctl+0x43/0x50 fs/ioctl.c:706 do_syscall_64+0x17a/0x530 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x453bc9 RSP: 002b:7fc5fba5eaf8 EFLAGS: 0212 ORIG_RAX: 0010 RAX: ffda RBX: 00708020 RCX: 00453bc9 RDX: 20003b38 RSI: c4c85512 RDI: 0005 RBP: 25a0 R08: R09: R10: R11: 0212 R12: 004aed78 R13: R14: 0005 R15: c4c85512 Allocated by task 27704: 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 kmem_cache_alloc_trace+0x152/0x780 mm/slab.c:3620 kmalloc include/linux/slab.h:512 [inline] kzalloc include/linux/slab.h:701 [inline] loopback_open+0x4d2/0x720 sound/drivers/aloop.c:704 snd_pcm_open_substream+0x174/0x250 sound/core/pcm_native.c:2391 snd_pcm_oss_open_file sound/core/oss/pcm_oss.c:2423 [inline] snd_pcm_oss_open+0x799/0xfc0 sound/core/oss/pcm_oss.c:2505 soundcore_open+0x2db/0x3e0 sound/sound_core.c:597 chrdev_open+0x1c6/0x450 fs/char_dev.c:417 do_dentry_open+0x520/0x7c0 fs/open.c:784 vfs_open+0xc5/0x120 fs/open.c:906 do_last fs/namei.c:3365 [inline] path_openat+0x1133/0x31a0 fs/namei.c:3501 do_filp_open+0x15a/0x1e0 fs/namei.c:3535 do_sys_open+0x464/0x540 fs/open.c:1093 __do_sys_open fs/open.c: [inline] __se_sys_open fs/open.c:1106 [inline] __x64_sys_open+0x4c/0x60 fs/open.c:1106 do_syscall_64+0x17a/0x530 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 27704: 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
Re: Unable to handle kernel paging request in snd_seq_oss_readq_puts
On Thu, Apr 26, 2018 at 09:17:45AM +0200, Takashi Iwai wrote: > On Thu, 26 Apr 2018 06:52:27 +0200, > DaeRyong Jeong wrote: > > > > We report the crash: > > unable to handle kernel paging request in snd_seq_oss_readq_puts > > > > This crash has been found in v4.16 using RaceFuzzer (a modified > > version of Syzkaller), which we describe more at the end of this > > report. Our analysis shows that the race occurs when invoking two > > syscalls concurrently, write$eventfd and write$sndseq. > > > > Analysis: > > We think the concurrent execution of snd_virmidi_output_trigger() and > > snd_midi_event_encode_byte() causes the crash. Since the first call site > > of snd_seq_kernel_client_dispatch() in snd_virmidi_output_trigger() is not > > protected by substream->runtime->lock, it is possible that > > snd_seq_oss_readq_puts() and snd_midi_event_encode_byte() are executed > > concurrently in the call sequences as below, and snd_seq_oss_readq_puts() > > accesses ev->data.ex.ptr before it is initialized. > > Thanks for the bug report and analysis. > > I guess that it's not about initialization but rather other way > round. The first task sends the pending event with SYSEX that > contains the buffer pointer in the event packet. Meanwhile, the > second task now starts processing the MIDI stream and overwrites this > event packet. So the data address that is being processed is > overwritten, and it leads to the crash. > > Below is the fix patch. It's totally untested, and I'd love to hear > if this really works. Could you give it a try? > > > thanks, > > Takashi > > -- 8< -- > From: Takashi Iwai <ti...@suse.de> > Subject: [PATCH] ALSA: seq: Fix races at MIDI encoding in > snd_virmidi_output_trigger() > > The sequencer virmidi code has an open race at its output trigger > callback: namely, virmidi keeps only one event packet for processing > while it doesn't protect for concurrent output trigger calls. > > snd_virmidi_output_trigger() tries to process the previously > unfinished event before starting encoding the given MIDI stream, but > this is done without any lock. Meanwhile, if another rawmidi stream > starts the output trigger, this proceeds further, and overwrites the > event package that is being processed in another thread. This > eventually corrupts and may lead to the invalid memory access if the > event type is like SYSEX. > > The fix is just to move the spinlock to cover both the pending event > and the new stream. > > The bug was spotted by a new fuzzer, RaceFuzzer. > > BugLink: http://lkml.kernel.org/r/20180426045223.ga15...@dragonet.kaist.ac.kr > Reported-by: DaeRyong Jeong <threeear...@gmail.com> > Cc: <sta...@vger.kernel.org> > Signed-off-by: Takashi Iwai <ti...@suse.de> > --- > sound/core/seq/seq_virmidi.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c > index f48a4cd24ffc..289ae6bb81d9 100644 > --- a/sound/core/seq/seq_virmidi.c > +++ b/sound/core/seq/seq_virmidi.c > @@ -174,12 +174,12 @@ static void snd_virmidi_output_trigger(struct > snd_rawmidi_substream *substream, > } > return; > } > + spin_lock_irqsave(>runtime->lock, flags); > if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { > if (snd_seq_kernel_client_dispatch(vmidi->client, > >event, in_atomic(), 0) < 0) > - return; > + goto out; > vmidi->event.type = SNDRV_SEQ_EVENT_NONE; > } > - spin_lock_irqsave(>runtime->lock, flags); > while (1) { > count = __snd_rawmidi_transmit_peek(substream, buf, > sizeof(buf)); > if (count <= 0) > -- > 2.16.3 > I'm really sorry to say this. Since we are implementing our fuzzer and our reproducer is not complete, we don't have a reproducer for this bug. We manually analyzed the crash using the crash log to spot where the race occurs. The patch looks good for me who don't understand the ALSA subsystem, but we can't test the patch. I'm sorry. Daeryong Jeong
Re: Unable to handle kernel paging request in snd_seq_oss_readq_puts
On Thu, Apr 26, 2018 at 09:17:45AM +0200, Takashi Iwai wrote: > On Thu, 26 Apr 2018 06:52:27 +0200, > DaeRyong Jeong wrote: > > > > We report the crash: > > unable to handle kernel paging request in snd_seq_oss_readq_puts > > > > This crash has been found in v4.16 using RaceFuzzer (a modified > > version of Syzkaller), which we describe more at the end of this > > report. Our analysis shows that the race occurs when invoking two > > syscalls concurrently, write$eventfd and write$sndseq. > > > > Analysis: > > We think the concurrent execution of snd_virmidi_output_trigger() and > > snd_midi_event_encode_byte() causes the crash. Since the first call site > > of snd_seq_kernel_client_dispatch() in snd_virmidi_output_trigger() is not > > protected by substream->runtime->lock, it is possible that > > snd_seq_oss_readq_puts() and snd_midi_event_encode_byte() are executed > > concurrently in the call sequences as below, and snd_seq_oss_readq_puts() > > accesses ev->data.ex.ptr before it is initialized. > > Thanks for the bug report and analysis. > > I guess that it's not about initialization but rather other way > round. The first task sends the pending event with SYSEX that > contains the buffer pointer in the event packet. Meanwhile, the > second task now starts processing the MIDI stream and overwrites this > event packet. So the data address that is being processed is > overwritten, and it leads to the crash. > > Below is the fix patch. It's totally untested, and I'd love to hear > if this really works. Could you give it a try? > > > thanks, > > Takashi > > -- 8< -- > From: Takashi Iwai > Subject: [PATCH] ALSA: seq: Fix races at MIDI encoding in > snd_virmidi_output_trigger() > > The sequencer virmidi code has an open race at its output trigger > callback: namely, virmidi keeps only one event packet for processing > while it doesn't protect for concurrent output trigger calls. > > snd_virmidi_output_trigger() tries to process the previously > unfinished event before starting encoding the given MIDI stream, but > this is done without any lock. Meanwhile, if another rawmidi stream > starts the output trigger, this proceeds further, and overwrites the > event package that is being processed in another thread. This > eventually corrupts and may lead to the invalid memory access if the > event type is like SYSEX. > > The fix is just to move the spinlock to cover both the pending event > and the new stream. > > The bug was spotted by a new fuzzer, RaceFuzzer. > > BugLink: http://lkml.kernel.org/r/20180426045223.ga15...@dragonet.kaist.ac.kr > Reported-by: DaeRyong Jeong > Cc: > Signed-off-by: Takashi Iwai > --- > sound/core/seq/seq_virmidi.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c > index f48a4cd24ffc..289ae6bb81d9 100644 > --- a/sound/core/seq/seq_virmidi.c > +++ b/sound/core/seq/seq_virmidi.c > @@ -174,12 +174,12 @@ static void snd_virmidi_output_trigger(struct > snd_rawmidi_substream *substream, > } > return; > } > + spin_lock_irqsave(>runtime->lock, flags); > if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { > if (snd_seq_kernel_client_dispatch(vmidi->client, > >event, in_atomic(), 0) < 0) > - return; > + goto out; > vmidi->event.type = SNDRV_SEQ_EVENT_NONE; > } > - spin_lock_irqsave(>runtime->lock, flags); > while (1) { > count = __snd_rawmidi_transmit_peek(substream, buf, > sizeof(buf)); > if (count <= 0) > -- > 2.16.3 > I'm really sorry to say this. Since we are implementing our fuzzer and our reproducer is not complete, we don't have a reproducer for this bug. We manually analyzed the crash using the crash log to spot where the race occurs. The patch looks good for me who don't understand the ALSA subsystem, but we can't test the patch. I'm sorry. Daeryong Jeong
Unable to handle kernel paging request in snd_seq_oss_readq_puts
We report the crash: unable to handle kernel paging request in snd_seq_oss_readq_puts This crash has been found in v4.16 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$eventfd and write$sndseq. Analysis: We think the concurrent execution of snd_virmidi_output_trigger() and snd_midi_event_encode_byte() causes the crash. Since the first call site of snd_seq_kernel_client_dispatch() in snd_virmidi_output_trigger() is not protected by substream->runtime->lock, it is possible that snd_seq_oss_readq_puts() and snd_midi_event_encode_byte() are executed concurrently in the call sequences as below, and snd_seq_oss_readq_puts() accesses ev->data.ex.ptr before it is initialized. Thread Interleaving: CPU1 (snd_virmidi_output_trigger) CPU2(snd_midi_event_encode_byte) ev->type = SNDRV_SEQ_EVENT_SYSEX; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { if (snd_seq_kernel_client_dispatch(vmidi->client, >event, in_atomic(), 0) < 0) ... /* In snd_seq_oss_readq_puts(), * data has the same value with ev->data.ext.ptr * which is not initialized yet */ rec.c[1] = *data++; ev->data.ext.len = dev->read; ev->data.ext.ptr = dev->buf; Call sequence: CPU1 snd_rawmidi_write snd_rawmidi_kernel_write1 snd_rawmidi_output_trigger snd_virmidi_output_trigger snd_seq_kernel_client_dispatch (line #178 in v4.16) snd_seq_deliver_event deliver_to_subscribers snd_seq_deliver_single_event.constprop.14 snd_seq_oss_event_input snd_seq_oss_midi_input send_midi_event snd_seq_oss_readq_sysex snd_seq_dump_var_event readq_dump_sysex snd_seq_oss_readq_puts CPU2 snd_rawmidi_write snd_rawmidi_kernel_write1 snd_rawmidi_output_trigger snd_virmidi_output_trigger snd_midi_event_encode snd_midi_event_encode_byte Crash log: == BUG: KASAN: null-ptr-deref in snd_seq_oss_readq_puts+0xc5/0x160 sound/core/seq/oss/seq_oss_readq.c:112 Read of size 1 at addr 0049 by task syz-executor0/12892 CPU: 1 PID: 12892 Comm: syz-executor0 Not tainted 4.16.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0x171/0x227 lib/dump_stack.c:53 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report.cold.7+0x13b/0x2f5 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load1+0x47/0x50 mm/kasan/kasan.c:695 snd_seq_oss_readq_puts+0xc5/0x160 sound/core/seq/oss/seq_oss_readq.c:112 readq_dump_sysex+0x3f/0x50 sound/core/seq/oss/seq_oss_readq.c:133 snd_seq_dump_var_event+0x375/0x3a0 sound/core/seq/seq_memory.c:107 snd_seq_oss_readq_sysex+0xec/0x100 sound/core/seq/oss/seq_oss_readq.c:146 send_midi_event sound/core/seq/oss/seq_oss_midi.c:615 [inline] snd_seq_oss_midi_input+0x332/0x710 sound/core/seq/oss/seq_oss_midi.c:535 snd_seq_oss_event_input+0xe9/0x130 sound/core/seq/oss/seq_oss_event.c:439 snd_seq_deliver_single_event.constprop.14+0x4bd/0x5a0 sound/core/seq/seq_clientmgr.c:622 deliver_to_subscribers sound/core/seq/seq_clientmgr.c:677 [inline] snd_seq_deliver_event+0x274/0x5d0 sound/core/seq/seq_clientmgr.c:812 snd_seq_kernel_client_dispatch+0xe2/0x100 sound/core/seq/seq_clientmgr.c:2330 snd_virmidi_output_trigger+0x156/0x420 sound/core/seq/seq_virmidi.c:178 snd_rawmidi_output_trigger sound/core/rawmidi.c:150 [inline] snd_rawmidi_kernel_write1+0x383/0x410 sound/core/rawmidi.c:1288 snd_rawmidi_write+0x241/0xa30 sound/core/rawmidi.c:1338 __vfs_write+0xed/0x510 fs/read_write.c:480 vfs_write+0x195/0x380 fs/read_write.c:544 SYSC_write fs/read_write.c:589 [inline] SyS_write+0xd7/0x1c0 fs/read_write.c:581 do_syscall_64+0x209/0x5d0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x42/0xb7 RIP: 0033:0x453bb9 RSP: 002b:7f46902c2af8 EFLAGS: 0212 ORIG_RAX: 0001 RAX: ffda RBX: 007080d8 RCX: 00453bb9 RDX: 00f3 RSI: 20004f0d RDI: 0006 RBP: 5ed0 R08: R09: R10: R11: 0212 R12: 004ab432 R13: R14: 0006 R15: 20004f0d == Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 12892 Comm: syz-executor0 Tainted: GB4.16.0 #1 Hardware name:
Unable to handle kernel paging request in snd_seq_oss_readq_puts
We report the crash: unable to handle kernel paging request in snd_seq_oss_readq_puts This crash has been found in v4.16 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, write$eventfd and write$sndseq. Analysis: We think the concurrent execution of snd_virmidi_output_trigger() and snd_midi_event_encode_byte() causes the crash. Since the first call site of snd_seq_kernel_client_dispatch() in snd_virmidi_output_trigger() is not protected by substream->runtime->lock, it is possible that snd_seq_oss_readq_puts() and snd_midi_event_encode_byte() are executed concurrently in the call sequences as below, and snd_seq_oss_readq_puts() accesses ev->data.ex.ptr before it is initialized. Thread Interleaving: CPU1 (snd_virmidi_output_trigger) CPU2(snd_midi_event_encode_byte) ev->type = SNDRV_SEQ_EVENT_SYSEX; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { if (snd_seq_kernel_client_dispatch(vmidi->client, >event, in_atomic(), 0) < 0) ... /* In snd_seq_oss_readq_puts(), * data has the same value with ev->data.ext.ptr * which is not initialized yet */ rec.c[1] = *data++; ev->data.ext.len = dev->read; ev->data.ext.ptr = dev->buf; Call sequence: CPU1 snd_rawmidi_write snd_rawmidi_kernel_write1 snd_rawmidi_output_trigger snd_virmidi_output_trigger snd_seq_kernel_client_dispatch (line #178 in v4.16) snd_seq_deliver_event deliver_to_subscribers snd_seq_deliver_single_event.constprop.14 snd_seq_oss_event_input snd_seq_oss_midi_input send_midi_event snd_seq_oss_readq_sysex snd_seq_dump_var_event readq_dump_sysex snd_seq_oss_readq_puts CPU2 snd_rawmidi_write snd_rawmidi_kernel_write1 snd_rawmidi_output_trigger snd_virmidi_output_trigger snd_midi_event_encode snd_midi_event_encode_byte Crash log: == BUG: KASAN: null-ptr-deref in snd_seq_oss_readq_puts+0xc5/0x160 sound/core/seq/oss/seq_oss_readq.c:112 Read of size 1 at addr 0049 by task syz-executor0/12892 CPU: 1 PID: 12892 Comm: syz-executor0 Not tainted 4.16.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0x171/0x227 lib/dump_stack.c:53 kasan_report_error mm/kasan/report.c:352 [inline] kasan_report.cold.7+0x13b/0x2f5 mm/kasan/report.c:412 check_memory_region_inline mm/kasan/kasan.c:260 [inline] __asan_load1+0x47/0x50 mm/kasan/kasan.c:695 snd_seq_oss_readq_puts+0xc5/0x160 sound/core/seq/oss/seq_oss_readq.c:112 readq_dump_sysex+0x3f/0x50 sound/core/seq/oss/seq_oss_readq.c:133 snd_seq_dump_var_event+0x375/0x3a0 sound/core/seq/seq_memory.c:107 snd_seq_oss_readq_sysex+0xec/0x100 sound/core/seq/oss/seq_oss_readq.c:146 send_midi_event sound/core/seq/oss/seq_oss_midi.c:615 [inline] snd_seq_oss_midi_input+0x332/0x710 sound/core/seq/oss/seq_oss_midi.c:535 snd_seq_oss_event_input+0xe9/0x130 sound/core/seq/oss/seq_oss_event.c:439 snd_seq_deliver_single_event.constprop.14+0x4bd/0x5a0 sound/core/seq/seq_clientmgr.c:622 deliver_to_subscribers sound/core/seq/seq_clientmgr.c:677 [inline] snd_seq_deliver_event+0x274/0x5d0 sound/core/seq/seq_clientmgr.c:812 snd_seq_kernel_client_dispatch+0xe2/0x100 sound/core/seq/seq_clientmgr.c:2330 snd_virmidi_output_trigger+0x156/0x420 sound/core/seq/seq_virmidi.c:178 snd_rawmidi_output_trigger sound/core/rawmidi.c:150 [inline] snd_rawmidi_kernel_write1+0x383/0x410 sound/core/rawmidi.c:1288 snd_rawmidi_write+0x241/0xa30 sound/core/rawmidi.c:1338 __vfs_write+0xed/0x510 fs/read_write.c:480 vfs_write+0x195/0x380 fs/read_write.c:544 SYSC_write fs/read_write.c:589 [inline] SyS_write+0xd7/0x1c0 fs/read_write.c:581 do_syscall_64+0x209/0x5d0 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x42/0xb7 RIP: 0033:0x453bb9 RSP: 002b:7f46902c2af8 EFLAGS: 0212 ORIG_RAX: 0001 RAX: ffda RBX: 007080d8 RCX: 00453bb9 RDX: 00f3 RSI: 20004f0d RDI: 0006 RBP: 5ed0 R08: R09: R10: R11: 0212 R12: 004ab432 R13: R14: 0006 R15: 20004f0d == Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 12892 Comm: syz-executor0 Tainted: GB4.16.0 #1 Hardware name:
Re: [PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
On Wed, Apr 25, 2018 at 03:39:48PM +0100, Alan Cox wrote: > On Wed, 25 Apr 2018 22:20:50 +0900 > DaeRyong Jeong <threeear...@gmail.com> wrote: > > > tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated > > by th->used and updates tb->used. > > But tty_insert_flip_string_fixed_flag() can be executed concurrently and > > tb->used can be updated improperly. > > The tty input layer does not work if it can be executed concurrently. If > that is happening in the pty code then the pty code is buggy and that > needs serializing on the inbound path. > > > > -static void tty_write_unlock(struct tty_struct *tty) > > +void tty_write_unlock(struct tty_struct *tty, int wakeup) > > { > > mutex_unlock(>atomic_write_lock); > > - wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + if (wakeup) { > > + wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + } > > And this may cause deadlocks. > > You don't actually need any of the wakeup changes in your code > > > diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c > > index d9b561d89432..a54ab91aec90 100644 > > --- a/drivers/tty/tty_ioctl.c > > +++ b/drivers/tty/tty_ioctl.c > > @@ -911,12 +911,17 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct > > file *file, > > spin_unlock_irq(>flow_lock); > > break; > > case TCOON: > > + if (tty_write_lock(tty, 0) < 0) > > + return -ERESTARTSYS; > > + > > spin_lock_irq(>flow_lock); > > if (tty->flow_stopped) { > > tty->flow_stopped = 0; > > __start_tty(tty); > > } > > spin_unlock_irq(>flow_lock); > > + > > + tty_write_unlock(tty, 0); > > If you just used these unmodified it would be simpler and as good, > however it won't actually fix anything. The pty layer is broken not this > code. Yes. I thought the wrong way to resolve the issue. > > The tty layer rule for all the input buffer handling is that you may not > call *any* of it from multiple threads at once. This works fine for > normal serial because the IRQ layer or the polling logic has that > property. > > The bug looks real, your diagnosis looks right, your fix sort of works > but isn't sufficient. > > So NAK. > > Alan With your comments, now I know that this patch is incorrect. Since the bug is real, I will send a new patch with considering all your comments above. Thank you a lot for all your comments. DaeRyong Jeong
Re: [PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
On Wed, Apr 25, 2018 at 03:39:48PM +0100, Alan Cox wrote: > On Wed, 25 Apr 2018 22:20:50 +0900 > DaeRyong Jeong wrote: > > > tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated > > by th->used and updates tb->used. > > But tty_insert_flip_string_fixed_flag() can be executed concurrently and > > tb->used can be updated improperly. > > The tty input layer does not work if it can be executed concurrently. If > that is happening in the pty code then the pty code is buggy and that > needs serializing on the inbound path. > > > > -static void tty_write_unlock(struct tty_struct *tty) > > +void tty_write_unlock(struct tty_struct *tty, int wakeup) > > { > > mutex_unlock(>atomic_write_lock); > > - wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + if (wakeup) { > > + wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + } > > And this may cause deadlocks. > > You don't actually need any of the wakeup changes in your code > > > diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c > > index d9b561d89432..a54ab91aec90 100644 > > --- a/drivers/tty/tty_ioctl.c > > +++ b/drivers/tty/tty_ioctl.c > > @@ -911,12 +911,17 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct > > file *file, > > spin_unlock_irq(>flow_lock); > > break; > > case TCOON: > > + if (tty_write_lock(tty, 0) < 0) > > + return -ERESTARTSYS; > > + > > spin_lock_irq(>flow_lock); > > if (tty->flow_stopped) { > > tty->flow_stopped = 0; > > __start_tty(tty); > > } > > spin_unlock_irq(>flow_lock); > > + > > + tty_write_unlock(tty, 0); > > If you just used these unmodified it would be simpler and as good, > however it won't actually fix anything. The pty layer is broken not this > code. Yes. I thought the wrong way to resolve the issue. > > The tty layer rule for all the input buffer handling is that you may not > call *any* of it from multiple threads at once. This works fine for > normal serial because the IRQ layer or the polling logic has that > property. > > The bug looks real, your diagnosis looks right, your fix sort of works > but isn't sufficient. > > So NAK. > > Alan With your comments, now I know that this patch is incorrect. Since the bug is real, I will send a new patch with considering all your comments above. Thank you a lot for all your comments. DaeRyong Jeong
Re: [PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
On Wed, Apr 25, 2018 at 03:41:59PM +0200, Greg KH wrote: > On Wed, Apr 25, 2018 at 10:20:50PM +0900, DaeRyong Jeong wrote: > > tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated > > by th->used and updates tb->used. > > But tty_insert_flip_string_fixed_flag() can be executed concurrently and > > tb->used can be updated improperly. > > It leads slab-out-of-bound write in tty_insert_flip_string_fixed_flag or > > slab-out-of-bounds read in flush_to_ldisc > > > > BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ > > 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 > > Write of size 1792 by task syz-executor0/30017 > > CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 > > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > > BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > > 88011638f888 81694cc3 88007d802140 > > 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 > > 8130075c 88011638f940 88007d802140 880194fcc121 > > Call Trace: > > __dump_stack lib/dump_stack.c:15 [inline] > > dump_stack+0xb3/0x110 lib/dump_stack.c:51 > > kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 > > print_address_description mm/kasan/report.c:194 [inline] > > kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 > > kasan_report+0x36/0x40 mm/kasan/report.c:303 > > check_memory_region_inline mm/kasan/kasan.c:292 [inline] > > check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 > > memcpy+0x37/0x50 mm/kasan/kasan.c:335 > > tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 > > tty_insert_flip_string include/linux/tty_flip.h:35 [inline] > > pty_write+0x7f/0xc0 drivers/tty/pty.c:115 > > n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 > > n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 > > tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 > > __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 > > __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 > > n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 > > n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 > > tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 > > vfs_ioctl fs/ioctl.c:43 [inline] > > do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 > > SYSC_ioctl fs/ioctl.c:694 [inline] > > SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 > > entry_SYSCALL_64_fastpath+0x1f/0xbd > > > > Call sequences are as follows. > > CPU0CPU1 > > n_tty_ioctl_helper n_tty_ioctl_helper > > __start_tty tty_send_xchar > > tty_wakeup pty_write > > n_hdlc_tty_wakeup tty_insert_flip_string > > n_hdlc_send_frames tty_insert_flip_string_fixed_flag > > pty_write > > tty_insert_flip_string > > tty_insert_flip_string_fixed_flag > > > > Acquire tty->atomic_write_lock by calling tty_write_lock() before > > __start_tty() since __start_tty() can sends frames. > > > > Signed-off-by: DaeRyong Jeong <threeear...@gmail.com> > > --- > > drivers/tty/tty_io.c| 16 +--- > > drivers/tty/tty_ioctl.c | 5 + > > include/linux/tty.h | 2 ++ > > 3 files changed, 16 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c > > index 63114ea35ec1..41f83bd4cc40 100644 > > --- a/drivers/tty/tty_io.c > > +++ b/drivers/tty/tty_io.c > > @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char > > __user *buf, size_t count, > > return i; > > } > > > > -static void tty_write_unlock(struct tty_struct *tty) > > +void tty_write_unlock(struct tty_struct *tty, int wakeup) > > { > > mutex_unlock(>atomic_write_lock); > > - wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + if (wakeup) { > > + wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + } > > Always run scripts/checkpatch.pl before sending patches out so you do > not get grumpy maintainers telling you to run scripts/checkpatch.pl :) Yes, I will. I will never corrupt a patch again. I'm sorry.. > > Anyway, these "bool" type options are horrid for trying to remember what > is happening here. You have to go look up what 1 or 0 is, right? > > How about two functions: > tty_write_unlock() > tty_write_unlock_wakup() > > and the second one calls the first and then does the wakeup? Yes. I agree that this has more readability and is much better to write a code. > > But are you sure this is the correct fix? What is protecting the race > from happening with this change? How do you know to call wakeup or not? > What determines which is better to do? As Alan cox commented, pty layer is broken, not this code. I thought wrong way to fix the issue. I will look into tty/pty code and think deeply. And then I will send a new patch. Thank you a lot for your comment! > > thanks, > > greg k-h
Re: [PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
On Wed, Apr 25, 2018 at 03:41:59PM +0200, Greg KH wrote: > On Wed, Apr 25, 2018 at 10:20:50PM +0900, DaeRyong Jeong wrote: > > tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated > > by th->used and updates tb->used. > > But tty_insert_flip_string_fixed_flag() can be executed concurrently and > > tb->used can be updated improperly. > > It leads slab-out-of-bound write in tty_insert_flip_string_fixed_flag or > > slab-out-of-bounds read in flush_to_ldisc > > > > BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ > > 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 > > Write of size 1792 by task syz-executor0/30017 > > CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 > > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > > BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > > 88011638f888 81694cc3 88007d802140 > > 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 > > 8130075c 88011638f940 88007d802140 880194fcc121 > > Call Trace: > > __dump_stack lib/dump_stack.c:15 [inline] > > dump_stack+0xb3/0x110 lib/dump_stack.c:51 > > kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 > > print_address_description mm/kasan/report.c:194 [inline] > > kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 > > kasan_report+0x36/0x40 mm/kasan/report.c:303 > > check_memory_region_inline mm/kasan/kasan.c:292 [inline] > > check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 > > memcpy+0x37/0x50 mm/kasan/kasan.c:335 > > tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 > > tty_insert_flip_string include/linux/tty_flip.h:35 [inline] > > pty_write+0x7f/0xc0 drivers/tty/pty.c:115 > > n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 > > n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 > > tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 > > __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 > > __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 > > n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 > > n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 > > tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 > > vfs_ioctl fs/ioctl.c:43 [inline] > > do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 > > SYSC_ioctl fs/ioctl.c:694 [inline] > > SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 > > entry_SYSCALL_64_fastpath+0x1f/0xbd > > > > Call sequences are as follows. > > CPU0CPU1 > > n_tty_ioctl_helper n_tty_ioctl_helper > > __start_tty tty_send_xchar > > tty_wakeup pty_write > > n_hdlc_tty_wakeup tty_insert_flip_string > > n_hdlc_send_frames tty_insert_flip_string_fixed_flag > > pty_write > > tty_insert_flip_string > > tty_insert_flip_string_fixed_flag > > > > Acquire tty->atomic_write_lock by calling tty_write_lock() before > > __start_tty() since __start_tty() can sends frames. > > > > Signed-off-by: DaeRyong Jeong > > --- > > drivers/tty/tty_io.c| 16 +--- > > drivers/tty/tty_ioctl.c | 5 + > > include/linux/tty.h | 2 ++ > > 3 files changed, 16 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c > > index 63114ea35ec1..41f83bd4cc40 100644 > > --- a/drivers/tty/tty_io.c > > +++ b/drivers/tty/tty_io.c > > @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char > > __user *buf, size_t count, > > return i; > > } > > > > -static void tty_write_unlock(struct tty_struct *tty) > > +void tty_write_unlock(struct tty_struct *tty, int wakeup) > > { > > mutex_unlock(>atomic_write_lock); > > - wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + if (wakeup) { > > + wake_up_interruptible_poll(>write_wait, EPOLLOUT); > > + } > > Always run scripts/checkpatch.pl before sending patches out so you do > not get grumpy maintainers telling you to run scripts/checkpatch.pl :) Yes, I will. I will never corrupt a patch again. I'm sorry.. > > Anyway, these "bool" type options are horrid for trying to remember what > is happening here. You have to go look up what 1 or 0 is, right? > > How about two functions: > tty_write_unlock() > tty_write_unlock_wakup() > > and the second one calls the first and then does the wakeup? Yes. I agree that this has more readability and is much better to write a code. > > But are you sure this is the correct fix? What is protecting the race > from happening with this change? How do you know to call wakeup or not? > What determines which is better to do? As Alan cox commented, pty layer is broken, not this code. I thought wrong way to fix the issue. I will look into tty/pty code and think deeply. And then I will send a new patch. Thank you a lot for your comment! > > thanks, > > greg k-h
[PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated by th->used and updates tb->used. But tty_insert_flip_string_fixed_flag() can be executed concurrently and tb->used can be updated improperly. It leads slab-out-of-bound write in tty_insert_flip_string_fixed_flag or slab-out-of-bounds read in flush_to_ldisc BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 Write of size 1792 by task syz-executor0/30017 CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 88011638f888 81694cc3 88007d802140 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 8130075c 88011638f940 88007d802140 880194fcc121 Call Trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xb3/0x110 lib/dump_stack.c:51 kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 print_address_description mm/kasan/report.c:194 [inline] kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 kasan_report+0x36/0x40 mm/kasan/report.c:303 check_memory_region_inline mm/kasan/kasan.c:292 [inline] check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 memcpy+0x37/0x50 mm/kasan/kasan.c:335 tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 tty_insert_flip_string include/linux/tty_flip.h:35 [inline] pty_write+0x7f/0xc0 drivers/tty/pty.c:115 n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 vfs_ioctl fs/ioctl.c:43 [inline] do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 SYSC_ioctl fs/ioctl.c:694 [inline] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 entry_SYSCALL_64_fastpath+0x1f/0xbd Call sequences are as follows. CPU0CPU1 n_tty_ioctl_helper n_tty_ioctl_helper __start_tty tty_send_xchar tty_wakeup pty_write n_hdlc_tty_wakeup tty_insert_flip_string n_hdlc_send_frames tty_insert_flip_string_fixed_flag pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag Acquire tty->atomic_write_lock by calling tty_write_lock() before __start_tty() since __start_tty() can sends frames. Signed-off-by: DaeRyong Jeong <threeear...@gmail.com> --- drivers/tty/tty_io.c| 16 +--- drivers/tty/tty_ioctl.c | 5 + include/linux/tty.h | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 63114ea35ec1..41f83bd4cc40 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, return i; } -static void tty_write_unlock(struct tty_struct *tty) +void tty_write_unlock(struct tty_struct *tty, int wakeup) { mutex_unlock(>atomic_write_lock); - wake_up_interruptible_poll(>write_wait, EPOLLOUT); + if (wakeup) { + wake_up_interruptible_poll(>write_wait, EPOLLOUT); + } } -static int tty_write_lock(struct tty_struct *tty, int ndelay) +int tty_write_lock(struct tty_struct *tty, int ndelay) { if (!mutex_trylock(>atomic_write_lock)) { if (ndelay) @@ -973,7 +975,7 @@ static inline ssize_t do_tty_write( ret = written; } out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return ret; } @@ -997,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) if (tty->ops->write && tty->count > 0) tty->ops->write(tty, msg, strlen(msg)); tty_unlock(tty); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); } return; } @@ -1092,7 +1094,7 @@ int tty_send_xchar(struct tty_struct *tty, char ch) if (was_stopped) stop_tty(tty); up_read(>termios_rwsem); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return 0; } @@ -2395,7 +2397,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration) msleep_interruptible(duration); retval = tty->ops->break_ctl(tty, 0); out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); if (signal_pending(current)) retval = -EINTR; } diff --git a/drivers/tty/tty_ioctl.c
[PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag
tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated by th->used and updates tb->used. But tty_insert_flip_string_fixed_flag() can be executed concurrently and tb->used can be updated improperly. It leads slab-out-of-bound write in tty_insert_flip_string_fixed_flag or slab-out-of-bounds read in flush_to_ldisc BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/ 0x130 drivers/tty/tty_buffer.c:316 at addr 880114fcc121 Write of size 1792 by task syz-executor0/30017 CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 88011638f888 81694cc3 88007d802140 880114fcb300 880114fcc300 880114fcb300 88011638f8b0 8130075c 88011638f940 88007d802140 880194fcc121 Call Trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xb3/0x110 lib/dump_stack.c:51 kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 print_address_description mm/kasan/report.c:194 [inline] kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283 kasan_report+0x36/0x40 mm/kasan/report.c:303 check_memory_region_inline mm/kasan/kasan.c:292 [inline] check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299 memcpy+0x37/0x50 mm/kasan/kasan.c:335 tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316 tty_insert_flip_string include/linux/tty_flip.h:35 [inline] pty_write+0x7f/0xc0 drivers/tty/pty.c:115 n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419 n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496 tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601 __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018 __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013 n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138 n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794 tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992 vfs_ioctl fs/ioctl.c:43 [inline] do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679 SYSC_ioctl fs/ioctl.c:694 [inline] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685 entry_SYSCALL_64_fastpath+0x1f/0xbd Call sequences are as follows. CPU0CPU1 n_tty_ioctl_helper n_tty_ioctl_helper __start_tty tty_send_xchar tty_wakeup pty_write n_hdlc_tty_wakeup tty_insert_flip_string n_hdlc_send_frames tty_insert_flip_string_fixed_flag pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag Acquire tty->atomic_write_lock by calling tty_write_lock() before __start_tty() since __start_tty() can sends frames. Signed-off-by: DaeRyong Jeong --- drivers/tty/tty_io.c| 16 +--- drivers/tty/tty_ioctl.c | 5 + include/linux/tty.h | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 63114ea35ec1..41f83bd4cc40 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, return i; } -static void tty_write_unlock(struct tty_struct *tty) +void tty_write_unlock(struct tty_struct *tty, int wakeup) { mutex_unlock(>atomic_write_lock); - wake_up_interruptible_poll(>write_wait, EPOLLOUT); + if (wakeup) { + wake_up_interruptible_poll(>write_wait, EPOLLOUT); + } } -static int tty_write_lock(struct tty_struct *tty, int ndelay) +int tty_write_lock(struct tty_struct *tty, int ndelay) { if (!mutex_trylock(>atomic_write_lock)) { if (ndelay) @@ -973,7 +975,7 @@ static inline ssize_t do_tty_write( ret = written; } out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return ret; } @@ -997,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) if (tty->ops->write && tty->count > 0) tty->ops->write(tty, msg, strlen(msg)); tty_unlock(tty); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); } return; } @@ -1092,7 +1094,7 @@ int tty_send_xchar(struct tty_struct *tty, char ch) if (was_stopped) stop_tty(tty); up_read(>termios_rwsem); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return 0; } @@ -2395,7 +2397,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration) msleep_interruptible(duration); retval = tty->ops->break_ctl(tty, 0); out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); if (signal_pending(current)) retval = -EINTR; } diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index d9b5
Re: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
I'm really sorry for you to wait. Since I made a few mistakes previously, I really don't want to make a mistake again. Therefore I have been reading documents more carefully and learning the approved email client (i.e., mutt). It is almost done. I will send a patch very soon. Again, I'm really sorry. Best regards, Daeryong Jeong. On Wed, Apr 25, 2018 at 9:53 PM, Greg KH <gre...@linuxfoundation.org> wrote: > On Thu, Apr 19, 2018 at 09:25:08PM +0900, DaeRyong Jeong wrote: >> The patch is attached at the end of this email and can be downloaded from >> here. >> https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.patch >> >> We applied the patch to v4.16 and tested our reproducer. we can't see the >> crash any longer. >> >> Our rationale is >> - Since tty_wakeup() called by __start_tty() sends frames, call >> tty_write_lock() before __start_tty(). >> - Since tty_write_lock() might sleep, locate tty_write_lock() before >> spin_lock_irq(>flow_lock). >> - Since wake_up_interruptible_poll() is called by both tty_write_unlock() >> and __start_tty(), Prevent calling wake_up_interruptible_poll() twice by >> adding the wakeup flag to tty_write_unlock() >> >> If there is something that we are missing or we are wrong, please let us >> know. >> >> >> Thank you. >> >> Best regards, >> Daeryong Jeong >> >> >> >> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c >> index 63114ea..09c76d3 100644 >> --- a/drivers/tty/tty_io.c >> +++ b/drivers/tty/tty_io.c >> @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char >> __user *buf, size_t count, >> return i; >> } >> >> -static void tty_write_unlock(struct tty_struct *tty) >> +void tty_write_unlock(struct tty_struct *tty, int wakeup) >> { >> mutex_unlock(>atomic_write_lock); >> - wake_up_interruptible_poll(>write_wait, EPOLLOUT); >> + if (wakeup) { >> + wake_up_interruptible_poll(>write_wait, EPOLLOUT); >> + } >> } >> > > > > What ever happened to this patch, did you end up resending it in a > non-corrupted way? > > thanks, > > greg k-h
Re: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
I'm really sorry for you to wait. Since I made a few mistakes previously, I really don't want to make a mistake again. Therefore I have been reading documents more carefully and learning the approved email client (i.e., mutt). It is almost done. I will send a patch very soon. Again, I'm really sorry. Best regards, Daeryong Jeong. On Wed, Apr 25, 2018 at 9:53 PM, Greg KH wrote: > On Thu, Apr 19, 2018 at 09:25:08PM +0900, DaeRyong Jeong wrote: >> The patch is attached at the end of this email and can be downloaded from >> here. >> https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.patch >> >> We applied the patch to v4.16 and tested our reproducer. we can't see the >> crash any longer. >> >> Our rationale is >> - Since tty_wakeup() called by __start_tty() sends frames, call >> tty_write_lock() before __start_tty(). >> - Since tty_write_lock() might sleep, locate tty_write_lock() before >> spin_lock_irq(>flow_lock). >> - Since wake_up_interruptible_poll() is called by both tty_write_unlock() >> and __start_tty(), Prevent calling wake_up_interruptible_poll() twice by >> adding the wakeup flag to tty_write_unlock() >> >> If there is something that we are missing or we are wrong, please let us >> know. >> >> >> Thank you. >> >> Best regards, >> Daeryong Jeong >> >> >> >> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c >> index 63114ea..09c76d3 100644 >> --- a/drivers/tty/tty_io.c >> +++ b/drivers/tty/tty_io.c >> @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char >> __user *buf, size_t count, >> return i; >> } >> >> -static void tty_write_unlock(struct tty_struct *tty) >> +void tty_write_unlock(struct tty_struct *tty, int wakeup) >> { >> mutex_unlock(>atomic_write_lock); >> - wake_up_interruptible_poll(>write_wait, EPOLLOUT); >> + if (wakeup) { >> + wake_up_interruptible_poll(>write_wait, EPOLLOUT); >> + } >> } >> > > > > What ever happened to this patch, did you end up resending it in a > non-corrupted way? > > thanks, > > greg k-h
Re: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
The patch is attached at the end of this email and can be downloaded from here. https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.patch We applied the patch to v4.16 and tested our reproducer. we can't see the crash any longer. Our rationale is - Since tty_wakeup() called by __start_tty() sends frames, call tty_write_lock() before __start_tty(). - Since tty_write_lock() might sleep, locate tty_write_lock() before spin_lock_irq(>flow_lock). - Since wake_up_interruptible_poll() is called by both tty_write_unlock() and __start_tty(), Prevent calling wake_up_interruptible_poll() twice by adding the wakeup flag to tty_write_unlock() If there is something that we are missing or we are wrong, please let us know. Thank you. Best regards, Daeryong Jeong diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 63114ea..09c76d3 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, return i; } -static void tty_write_unlock(struct tty_struct *tty) +void tty_write_unlock(struct tty_struct *tty, int wakeup) { mutex_unlock(>atomic_write_lock); - wake_up_interruptible_poll(>write_wait, EPOLLOUT); + if (wakeup) { + wake_up_interruptible_poll(>write_wait, EPOLLOUT); + } } -static int tty_write_lock(struct tty_struct *tty, int ndelay) +int tty_write_lock(struct tty_struct *tty, int ndelay) { if (!mutex_trylock(>atomic_write_lock)) { if (ndelay) @@ -973,7 +975,7 @@ static inline ssize_t do_tty_write( ret = written; } out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return ret; } @@ -997,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) if (tty->ops->write && tty->count > 0) tty->ops->write(tty, msg, strlen(msg)); tty_unlock(tty); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); } return; } @@ -1092,7 +1094,7 @@ int tty_send_xchar(struct tty_struct *tty, char ch) if (was_stopped) stop_tty(tty); up_read(>termios_rwsem); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return 0; } @@ -2395,7 +2397,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration) msleep_interruptible(duration); retval = tty->ops->break_ctl(tty, 0); out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); if (signal_pending(current)) retval = -EINTR; } diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index d9b561d..f331e99 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -911,12 +911,17 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, spin_unlock_irq(>flow_lock); break; case TCOON: + if (tty_write_lock(tty, 0) < 0) + return -ERESTARTSYS; + spin_lock_irq(>flow_lock); if (tty->flow_stopped) { tty->flow_stopped = 0; __start_tty(tty); } spin_unlock_irq(>flow_lock); + + tty_write_unlock(tty, 0); break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) diff --git a/include/linux/tty.h b/include/linux/tty.h index 47f8af2..5bdf928 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -458,6 +458,8 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) return tty; } +extern void tty_write_unlock(struct tty_struct *tty, int wakeup); +extern int tty_write_lock(struct tty_struct *tty, int ndelay); extern const char *tty_driver_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); On Thu, Apr 19, 2018 at 5:17 PM, Greg KH <gre...@linuxfoundation.org> wrote: > On Thu, Apr 19, 2018 at 05:09:16PM +0900, DaeRyong Jeong wrote: >> We report the crash: >> KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag >> >> This crash has been found in v4.16 using RaceFuzzer (a modified >> version of Syzkaller), which we describe more at the end of this >> report. Our analysis shows that the race occurs when invoking two >> syscalls concurrently, ioctl$TCXONC(r0, 0x540a, 0x2) and >> ioctl$TCXONC(r0, 0x540a, 0x1). > > Nice! > > Do you have a kernel patch to resolve this issue? > > thanks, > > greg k-h
Re: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
The patch is attached at the end of this email and can be downloaded from here. https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.patch We applied the patch to v4.16 and tested our reproducer. we can't see the crash any longer. Our rationale is - Since tty_wakeup() called by __start_tty() sends frames, call tty_write_lock() before __start_tty(). - Since tty_write_lock() might sleep, locate tty_write_lock() before spin_lock_irq(>flow_lock). - Since wake_up_interruptible_poll() is called by both tty_write_unlock() and __start_tty(), Prevent calling wake_up_interruptible_poll() twice by adding the wakeup flag to tty_write_unlock() If there is something that we are missing or we are wrong, please let us know. Thank you. Best regards, Daeryong Jeong diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 63114ea..09c76d3 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, return i; } -static void tty_write_unlock(struct tty_struct *tty) +void tty_write_unlock(struct tty_struct *tty, int wakeup) { mutex_unlock(>atomic_write_lock); - wake_up_interruptible_poll(>write_wait, EPOLLOUT); + if (wakeup) { + wake_up_interruptible_poll(>write_wait, EPOLLOUT); + } } -static int tty_write_lock(struct tty_struct *tty, int ndelay) +int tty_write_lock(struct tty_struct *tty, int ndelay) { if (!mutex_trylock(>atomic_write_lock)) { if (ndelay) @@ -973,7 +975,7 @@ static inline ssize_t do_tty_write( ret = written; } out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return ret; } @@ -997,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) if (tty->ops->write && tty->count > 0) tty->ops->write(tty, msg, strlen(msg)); tty_unlock(tty); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); } return; } @@ -1092,7 +1094,7 @@ int tty_send_xchar(struct tty_struct *tty, char ch) if (was_stopped) stop_tty(tty); up_read(>termios_rwsem); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return 0; } @@ -2395,7 +2397,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration) msleep_interruptible(duration); retval = tty->ops->break_ctl(tty, 0); out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); if (signal_pending(current)) retval = -EINTR; } diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index d9b561d..f331e99 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -911,12 +911,17 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, spin_unlock_irq(>flow_lock); break; case TCOON: + if (tty_write_lock(tty, 0) < 0) + return -ERESTARTSYS; + spin_lock_irq(>flow_lock); if (tty->flow_stopped) { tty->flow_stopped = 0; __start_tty(tty); } spin_unlock_irq(>flow_lock); + + tty_write_unlock(tty, 0); break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) diff --git a/include/linux/tty.h b/include/linux/tty.h index 47f8af2..5bdf928 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -458,6 +458,8 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) return tty; } +extern void tty_write_unlock(struct tty_struct *tty, int wakeup); +extern int tty_write_lock(struct tty_struct *tty, int ndelay); extern const char *tty_driver_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); On Thu, Apr 19, 2018 at 5:17 PM, Greg KH wrote: > On Thu, Apr 19, 2018 at 05:09:16PM +0900, DaeRyong Jeong wrote: >> We report the crash: >> KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag >> >> This crash has been found in v4.16 using RaceFuzzer (a modified >> version of Syzkaller), which we describe more at the end of this >> report. Our analysis shows that the race occurs when invoking two >> syscalls concurrently, ioctl$TCXONC(r0, 0x540a, 0x2) and >> ioctl$TCXONC(r0, 0x540a, 0x1). > > Nice! > > Do you have a kernel patch to resolve this issue? > > thanks, > > greg k-h
KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
We report the crash: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag This crash has been found in v4.16 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, ioctl$TCXONC(r0, 0x540a, 0x2) and ioctl$TCXONC(r0, 0x540a, 0x1). C repro code: https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.c kernel config v4.16: https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.config Analysis: We think the concurrent execution of tty_insert_filp_string_fixed_flag causes the crash. Unsynchronized copying data to a buffer and updating an offset may cause crashes slab-out-of-bounds write in tty_insert_flip_string_fixed_flag or slab-out-of-bounds read in flush_to_ldisc. Call Sequence (v4.16): CPU0 (ioctl$TCXONC(r0, 0x540a, 0x1)) n_tty_ioctl_helper __start_tty tty_wakeup n_hdlc_tty_wakeup n_hdlc_send_frames pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag CPU1 (ioctl$TCXONC(r0, 0x540a, 0x2)) n_tty_ioctl_helper tty_send_xchar pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag Crash log: == [ 149.605804] BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.606914] Write of size 1 at addr 8800b1373ae0 by task a.out/3899 [ 149.607801] [ 149.608033] CPU: 0 PID: 3899 Comm: a.out Not tainted 4.16.0 #1 [ 149.608852] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 149.610040] Call Trace: [ 149.610379] dump_stack+0x155/0x1f6 [ 149.610847] ? arch_local_irq_restore+0x3c/0x3c [ 149.611438] ? show_regs_print_info+0x18/0x18 [ 149.612012] ? flush_to_ldisc+0x310/0x310 [ 149.612548] ? tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.613273] print_address_description+0x73/0x250 [ 149.613889] ? tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.614609] kasan_report+0x23f/0x360 [ 149.615106] check_memory_region+0x140/0x1a0 [ 149.615669] memcpy+0x37/0x50 [ 149.616076] tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.616807] pty_write+0x7f/0xc0 [ 149.617248] tty_send_xchar+0x114/0x180 [ 149.617765] n_tty_ioctl_helper+0xec/0x1e0 [ 149.618312] n_hdlc_tty_ioctl+0x118/0x370 [ 149.618848] ? n_hdlc_tty_wakeup+0xa0/0xa0 [ 149.619410] ? ldsem_down_read+0x37/0x40 [ 149.619923] ? ldsem_down_read+0x37/0x40 [ 149.620474] tty_ioctl+0x292/0x1030 [ 149.620914] ? n_hdlc_tty_wakeup+0xa0/0xa0 [ 149.621431] ? tty_vhangup+0x30/0x30 [ 149.621883] ? rcu_is_watching+0x8f/0xd0 [ 149.622378] ? rcutorture_record_progress+0x10/0x10 [ 149.622998] ? __lock_is_held+0x30/0xc0 [ 149.623505] ? ___might_sleep+0x258/0x340 [ 149.624010] ? check_same_owner+0x240/0x240 [ 149.624535] ? __vfs_write+0xe5/0x480 [ 149.624997] ? rcu_note_context_switch+0x4e0/0x4e0 [ 149.625594] ? rcu_note_context_switch+0x4e0/0x4e0 [ 149.626186] ? kernel_read+0xa0/0xa0 [ 149.626648] ? tty_vhangup+0x30/0x30 [ 149.627099] do_vfs_ioctl+0x145/0xd00 [ 149.627557] ? _cond_resched+0x14/0x30 [ 149.628039] ? ioctl_preallocate+0x1c0/0x1c0 [ 149.628583] ? selinux_capable+0x40/0x40 [ 149.629087] ? SyS_futex+0x22b/0x2f0 [ 149.629562] ? security_file_ioctl+0x62/0x90 [ 149.630094] ? security_file_ioctl+0x6e/0x90 [ 149.630633] SyS_ioctl+0x8f/0xc0 [ 149.631049] ? do_vfs_ioctl+0xd00/0xd00 [ 149.631534] do_syscall_64+0x1f2/0x530 [ 149.632017] ? syscall_return_slowpath+0x360/0x360 [ 149.632632] ? syscall_return_slowpath+0x1fd/0x360 [ 149.633204] ? mark_held_locks+0x23/0xa0 [ 149.633675] ? entry_SYSCALL_64_after_hwframe+0x52/0xb7 [ 149.634295] ? trace_hardirqs_off_caller+0xb5/0x120 [ 149.634874] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 149.635444] entry_SYSCALL_64_after_hwframe+0x42/0xb7 [ 149.636051] RIP: 0033:0x7f4079e59b79 [ 149.636493] RSP: 002b:7f4079d7ddd8 EFLAGS: 0246 ORIG_RAX: 0010 [ 149.637377] RAX: ffda RBX: 0001 RCX: 7f4079e59b79 [ 149.638194] RDX: 0002 RSI: 540a RDI: 0062 [ 149.639014] RBP: 7f4079d7de20 R08: R09: [ 149.639839] R10: R11: 0246 R12: 0072fef0 [ 149.640675] R13: 7f4079d7e9c0 R14: 7f407a548040 R15: 0003 [ 149.641529] [ 149.641722] Allocated by task 3899: [ 149.642140] save_stack+0x43/0xd0 [ 149.642539] kasan_kmalloc+0xae/0xe0 [ 149.642968] __kmalloc+0x162/0x760 [ 149.643376] __tty_buffer_request_room+0x1cb/0x400 [ 149.643934] tty_insert_flip_string_fixed_flag+0x67/0x130 [ 149.644585] pty_write+0x7f/0xc0 [ 149.644959] n_hdlc_send_frames+0x1a4/0x340 [ 149.645432] n_hdlc_tty_write+0x3f3/0x480 [ 149.645887] tty_write+0x320/0x510 [ 149.646275]
KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag
We report the crash: KASAN: slab-out-of-bounds Write in tty_insert_flip_string_fixed_flag This crash has been found in v4.16 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, ioctl$TCXONC(r0, 0x540a, 0x2) and ioctl$TCXONC(r0, 0x540a, 0x1). C repro code: https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.c kernel config v4.16: https://kiwi.cs.purdue.edu/static/race-fuzzer/tty_insert_flip_string_fixed_flag.config Analysis: We think the concurrent execution of tty_insert_filp_string_fixed_flag causes the crash. Unsynchronized copying data to a buffer and updating an offset may cause crashes slab-out-of-bounds write in tty_insert_flip_string_fixed_flag or slab-out-of-bounds read in flush_to_ldisc. Call Sequence (v4.16): CPU0 (ioctl$TCXONC(r0, 0x540a, 0x1)) n_tty_ioctl_helper __start_tty tty_wakeup n_hdlc_tty_wakeup n_hdlc_send_frames pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag CPU1 (ioctl$TCXONC(r0, 0x540a, 0x2)) n_tty_ioctl_helper tty_send_xchar pty_write tty_insert_flip_string tty_insert_flip_string_fixed_flag Crash log: == [ 149.605804] BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.606914] Write of size 1 at addr 8800b1373ae0 by task a.out/3899 [ 149.607801] [ 149.608033] CPU: 0 PID: 3899 Comm: a.out Not tainted 4.16.0 #1 [ 149.608852] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 149.610040] Call Trace: [ 149.610379] dump_stack+0x155/0x1f6 [ 149.610847] ? arch_local_irq_restore+0x3c/0x3c [ 149.611438] ? show_regs_print_info+0x18/0x18 [ 149.612012] ? flush_to_ldisc+0x310/0x310 [ 149.612548] ? tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.613273] print_address_description+0x73/0x250 [ 149.613889] ? tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.614609] kasan_report+0x23f/0x360 [ 149.615106] check_memory_region+0x140/0x1a0 [ 149.615669] memcpy+0x37/0x50 [ 149.616076] tty_insert_flip_string_fixed_flag+0xaf/0x130 [ 149.616807] pty_write+0x7f/0xc0 [ 149.617248] tty_send_xchar+0x114/0x180 [ 149.617765] n_tty_ioctl_helper+0xec/0x1e0 [ 149.618312] n_hdlc_tty_ioctl+0x118/0x370 [ 149.618848] ? n_hdlc_tty_wakeup+0xa0/0xa0 [ 149.619410] ? ldsem_down_read+0x37/0x40 [ 149.619923] ? ldsem_down_read+0x37/0x40 [ 149.620474] tty_ioctl+0x292/0x1030 [ 149.620914] ? n_hdlc_tty_wakeup+0xa0/0xa0 [ 149.621431] ? tty_vhangup+0x30/0x30 [ 149.621883] ? rcu_is_watching+0x8f/0xd0 [ 149.622378] ? rcutorture_record_progress+0x10/0x10 [ 149.622998] ? __lock_is_held+0x30/0xc0 [ 149.623505] ? ___might_sleep+0x258/0x340 [ 149.624010] ? check_same_owner+0x240/0x240 [ 149.624535] ? __vfs_write+0xe5/0x480 [ 149.624997] ? rcu_note_context_switch+0x4e0/0x4e0 [ 149.625594] ? rcu_note_context_switch+0x4e0/0x4e0 [ 149.626186] ? kernel_read+0xa0/0xa0 [ 149.626648] ? tty_vhangup+0x30/0x30 [ 149.627099] do_vfs_ioctl+0x145/0xd00 [ 149.627557] ? _cond_resched+0x14/0x30 [ 149.628039] ? ioctl_preallocate+0x1c0/0x1c0 [ 149.628583] ? selinux_capable+0x40/0x40 [ 149.629087] ? SyS_futex+0x22b/0x2f0 [ 149.629562] ? security_file_ioctl+0x62/0x90 [ 149.630094] ? security_file_ioctl+0x6e/0x90 [ 149.630633] SyS_ioctl+0x8f/0xc0 [ 149.631049] ? do_vfs_ioctl+0xd00/0xd00 [ 149.631534] do_syscall_64+0x1f2/0x530 [ 149.632017] ? syscall_return_slowpath+0x360/0x360 [ 149.632632] ? syscall_return_slowpath+0x1fd/0x360 [ 149.633204] ? mark_held_locks+0x23/0xa0 [ 149.633675] ? entry_SYSCALL_64_after_hwframe+0x52/0xb7 [ 149.634295] ? trace_hardirqs_off_caller+0xb5/0x120 [ 149.634874] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 149.635444] entry_SYSCALL_64_after_hwframe+0x42/0xb7 [ 149.636051] RIP: 0033:0x7f4079e59b79 [ 149.636493] RSP: 002b:7f4079d7ddd8 EFLAGS: 0246 ORIG_RAX: 0010 [ 149.637377] RAX: ffda RBX: 0001 RCX: 7f4079e59b79 [ 149.638194] RDX: 0002 RSI: 540a RDI: 0062 [ 149.639014] RBP: 7f4079d7de20 R08: R09: [ 149.639839] R10: R11: 0246 R12: 0072fef0 [ 149.640675] R13: 7f4079d7e9c0 R14: 7f407a548040 R15: 0003 [ 149.641529] [ 149.641722] Allocated by task 3899: [ 149.642140] save_stack+0x43/0xd0 [ 149.642539] kasan_kmalloc+0xae/0xe0 [ 149.642968] __kmalloc+0x162/0x760 [ 149.643376] __tty_buffer_request_room+0x1cb/0x400 [ 149.643934] tty_insert_flip_string_fixed_flag+0x67/0x130 [ 149.644585] pty_write+0x7f/0xc0 [ 149.644959] n_hdlc_send_frames+0x1a4/0x340 [ 149.645432] n_hdlc_tty_write+0x3f3/0x480 [ 149.645887] tty_write+0x320/0x510 [ 149.646275]
Re: kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE!
Hello. We have analyzed the cause of the crash, kernel BUG at net/packet/af_packet.c:LINE!, which is found by RaceFuzzer (a modified version of Syzkaller) in v4.16-rc7. Since struct packet_sock's member variables, running, has_vnet_hdr, origdev and auxdata are declared as bitfields, accessing these variables can race if there is no synchronization mechanism. We think racing between following lines in af_packet.c causes the crash. In function __unregister_prot_hook, po->running = 0; In function packet_setsockopt, po->has_vnet_hdr = !!val; Analysis: CPU0 pakcet_setsockopt po->has_vnet_hdr = !!val; CPU1 packet_do_bind __unregister_prot_hook po->running = 0; In the CPU1, the value of po->running should become 0, but because of racing, it is possible that po->running can keep the value 1. Consequently, after returning from __unregister_prot_hook, BUG_ON at net/packet/af_packet.c:3107 can be triggered. Possible interleaving between racy C source lines is as follows (built with gcc-7.1.0). CPU0 (po->has_vnet_hdr = !!val)CPU1 (po->running = 0) movzbl 0x6e0(%r15),%eax andb $0xfe,0x6e0(%r13) shl$0x3,%r12d and$0xfff7,%eax or %r12d,%eax mov%al,0x6e0(%r15) Please, check out the following reproducer. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c kernel config v4.16-rc3 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config kernel config v4.16-rc7 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config kernel config v4.15.14 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the user space, its reproducibility is limited (reproduction may take from 1 second to 10 minutes (or even more), depending on a bug). This is because, while RaceFuzzer precisely interleaves the scheduling at the kernel's instruction level when finding this bug, C repro cannot fully utilize such a feature. Please disregard all code related to "should_hypercall" in the C repro, as this is only for our debugging purposes using our own hypervisor. On Sat, Mar 31, 2018 at 1:33 AM, DaeRyong Jeong <threeear...@gmail.com> wrote: > We report the crash: kernel BUG at > /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE! > > This crash has been found in v4.16-rc3 using RaceFuzzer (a modified > version of Syzkaller), which we describe more at the end of this > report. Our analysis shows that the race occurs when invoking two > syscalls concurrently, (setsockopt$packet_int) and (bind$packet). > We have confirmed that the kernel v4.16-rc3, v4.16-rc7, and v4.15.14 > built with gcc 7.1.0 are crashing by running the provided C repro > program within a few minutes (5 minutes). > Note that this crash can be triggered from the user space. > > C repro code : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c > kernel config v4.16-rc3 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config > kernel config v4.16-rc7 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config > kernel config v4.15.14 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config > > [ 881.047513] [ cut here ] > [ 881.048416] kernel BUG at > /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! > [ 881.050014] invalid opcode: [#1] SMP KASAN > [ 881.050698] Dumping ftrace buffer: > [ 881.051244](ftrace buffer empty) > [ 881.051768] Modules linked in: > [ 881.052236] CPU: 1 PID: 18247 Comm: syz-executor0 Not tainted 4.16.0-rc3 #1 > [ 881.053247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > [ 881.054880] RIP: 0010:packet_do_bind+0x88d/0x950 > [ 881.03] RSP: 0018:8802231d7b08 EFLAGS: 00010212 > [ 881.056310] RAX: 0001 RBX: 88
Re: kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE!
Hello. We have analyzed the cause of the crash, kernel BUG at net/packet/af_packet.c:LINE!, which is found by RaceFuzzer (a modified version of Syzkaller) in v4.16-rc7. Since struct packet_sock's member variables, running, has_vnet_hdr, origdev and auxdata are declared as bitfields, accessing these variables can race if there is no synchronization mechanism. We think racing between following lines in af_packet.c causes the crash. In function __unregister_prot_hook, po->running = 0; In function packet_setsockopt, po->has_vnet_hdr = !!val; Analysis: CPU0 pakcet_setsockopt po->has_vnet_hdr = !!val; CPU1 packet_do_bind __unregister_prot_hook po->running = 0; In the CPU1, the value of po->running should become 0, but because of racing, it is possible that po->running can keep the value 1. Consequently, after returning from __unregister_prot_hook, BUG_ON at net/packet/af_packet.c:3107 can be triggered. Possible interleaving between racy C source lines is as follows (built with gcc-7.1.0). CPU0 (po->has_vnet_hdr = !!val)CPU1 (po->running = 0) movzbl 0x6e0(%r15),%eax andb $0xfe,0x6e0(%r13) shl$0x3,%r12d and$0xfff7,%eax or %r12d,%eax mov%al,0x6e0(%r15) Please, check out the following reproducer. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c kernel config v4.16-rc3 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config kernel config v4.16-rc7 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config kernel config v4.15.14 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the user space, its reproducibility is limited (reproduction may take from 1 second to 10 minutes (or even more), depending on a bug). This is because, while RaceFuzzer precisely interleaves the scheduling at the kernel's instruction level when finding this bug, C repro cannot fully utilize such a feature. Please disregard all code related to "should_hypercall" in the C repro, as this is only for our debugging purposes using our own hypervisor. On Sat, Mar 31, 2018 at 1:33 AM, DaeRyong Jeong wrote: > We report the crash: kernel BUG at > /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE! > > This crash has been found in v4.16-rc3 using RaceFuzzer (a modified > version of Syzkaller), which we describe more at the end of this > report. Our analysis shows that the race occurs when invoking two > syscalls concurrently, (setsockopt$packet_int) and (bind$packet). > We have confirmed that the kernel v4.16-rc3, v4.16-rc7, and v4.15.14 > built with gcc 7.1.0 are crashing by running the provided C repro > program within a few minutes (5 minutes). > Note that this crash can be triggered from the user space. > > C repro code : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c > kernel config v4.16-rc3 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config > kernel config v4.16-rc7 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config > kernel config v4.15.14 : > https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config > > [ 881.047513] [ cut here ] > [ 881.048416] kernel BUG at > /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! > [ 881.050014] invalid opcode: [#1] SMP KASAN > [ 881.050698] Dumping ftrace buffer: > [ 881.051244](ftrace buffer empty) > [ 881.051768] Modules linked in: > [ 881.052236] CPU: 1 PID: 18247 Comm: syz-executor0 Not tainted 4.16.0-rc3 #1 > [ 881.053247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > [ 881.054880] RIP: 0010:packet_do_bind+0x88d/0x950 > [ 881.03] RSP: 0018:8802231d7b08 EFLAGS: 00010212 > [ 881.056310] RAX: 0001 RBX: 8800af831740 RCX: > c9
Re: WARNING in refcount_dec
Hello. We have analyzed the cause of the crash in v4.16-rc3, WARNING in refcount_dec, which is found by RaceFuzzer (a modified version of Syzkaller). Since struct packet_sock's member variables, running, has_vnet_hdr, origdev and auxdata are declared as bitfields, accessing these variables can race if there is no synchronization mechanism. We think racing between following lines in af_packet.c causes the crash. In function __unregister_prot_hook, po->running = 0; In function packet_setsockopt, po->has_vnet_hdr = !!val; Analysis: CPU0 pakcet_setsockopt po->has_vnet_hdr = !!val; CPU1 packet_setsockop packet_set_ring __unregister_prot_hook po->running = 0; In the CPU1, the value of po->running should become 0, but because of racing, it is possible that po->running can keep the value 1. Consequently, the followings can happen. - When packet_set_ring calls register_prot_hook, register_prot_hook return immediately without calling sock_hold(sk). - When packet_release is called, __unregister_prot_hook will be called because po->running == 1 and sk->sk_refcnt hits zero. Possible interleaving between racy C source lines is as follows (built with gcc-7.1.0). CPU0 (po->has_vnet_hdr = !!val) CPU1 (po->running = 0) movzbl 0x6e0(%r15),%eax andb $0xfe,0x6e0(%r13) shl$0x3,%r12d and$0xfff7,%eax or %r12d,%eax mov%al,0x6e0(%r15) Please, check out the following reproducer. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/repro-refcount_dec.c kernel config: https://kiwi.cs.purdue.edu/static/race-fuzzer/kernel-config-v4.16-rc3 Since there is a small room to race, it may take a long time to reproduce the crash. = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the user space, its reproducibility is limited (reproduction may take from 1 second to 10 minutes (or even more), depending on a bug). This is because, while RaceFuzzer precisely interleaves the scheduling at the kernel's instruction level when finding this bug, C repro cannot fully utilize such a feature. Please disregard all code related to "should_hypercall" in the C repro, as this is only for our debugging purposes using our own hypervisor. On Tue, Apr 3, 2018 at 1:12 PM, DaeRyong Jeong <threeear...@gmail.com> wrote: > No. Only the first crash (WARNING in refcount_dec) is reproduced by > the attached reproducer. > > The second crash (kernel bug at af_packet.c:3107) is reproduced by > another reproducer. > We reported it here. > http://lkml.iu.edu/hypermail/linux/kernel/1803.3/05324.html > > On Sun, Apr 1, 2018 at 4:38 PM, Willem de Bruijn > <willemdebruijn.ker...@gmail.com> wrote: >> On Thu, Mar 29, 2018 at 1:16 AM, Cong Wang <xiyou.wangc...@gmail.com> wrote: >>> (Cc'ing netdev and Willem) >>> >>> On Wed, Mar 28, 2018 at 12:03 PM, Byoungyoung Lee >>> <byoungyo...@purdue.edu> wrote: >>>> Another crash patterns observed: race between (setsockopt$packet_int) >>>> and (bind$packet). >>>> >>>> -- >>>> [ 357.731597] kernel BUG at >>>> /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! >>>> [ 357.733382] invalid opcode: [#1] SMP KASAN >>>> [ 357.734017] Modules linked in: >>>> [ 357.734662] CPU: 1 PID: 3871 Comm: repro.exe Not tainted 4.16.0-rc3 #1 >>>> [ 357.735791] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), >>>> BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 >>>> [ 357.737434] RIP: 0010:packet_do_bind+0x88d/0x950 >>>> [ 357.738121] RSP: 0018:8800b2787b08 EFLAGS: 00010293 >>>> [ 357.738906] RAX: 8800b2fdc780 RBX: 880234358cc0 RCX: >>>> 838b244c >>>> [ 357.739905] RDX: RSI: 838b257d RDI: >>>> 0001 >>>> [ 357.741315] RBP: 8800b2787c10 R08: 8800b2fdc780 R09: >>>> >>>> [ 357.743055] R10:
Re: WARNING in refcount_dec
Hello. We have analyzed the cause of the crash in v4.16-rc3, WARNING in refcount_dec, which is found by RaceFuzzer (a modified version of Syzkaller). Since struct packet_sock's member variables, running, has_vnet_hdr, origdev and auxdata are declared as bitfields, accessing these variables can race if there is no synchronization mechanism. We think racing between following lines in af_packet.c causes the crash. In function __unregister_prot_hook, po->running = 0; In function packet_setsockopt, po->has_vnet_hdr = !!val; Analysis: CPU0 pakcet_setsockopt po->has_vnet_hdr = !!val; CPU1 packet_setsockop packet_set_ring __unregister_prot_hook po->running = 0; In the CPU1, the value of po->running should become 0, but because of racing, it is possible that po->running can keep the value 1. Consequently, the followings can happen. - When packet_set_ring calls register_prot_hook, register_prot_hook return immediately without calling sock_hold(sk). - When packet_release is called, __unregister_prot_hook will be called because po->running == 1 and sk->sk_refcnt hits zero. Possible interleaving between racy C source lines is as follows (built with gcc-7.1.0). CPU0 (po->has_vnet_hdr = !!val) CPU1 (po->running = 0) movzbl 0x6e0(%r15),%eax andb $0xfe,0x6e0(%r13) shl$0x3,%r12d and$0xfff7,%eax or %r12d,%eax mov%al,0x6e0(%r15) Please, check out the following reproducer. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/repro-refcount_dec.c kernel config: https://kiwi.cs.purdue.edu/static/race-fuzzer/kernel-config-v4.16-rc3 Since there is a small room to race, it may take a long time to reproduce the crash. = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in scheduling). RaceFuzzer's C repro always pinpoints two racy syscalls. Since C repro's scheduling synchronization should be performed at the user space, its reproducibility is limited (reproduction may take from 1 second to 10 minutes (or even more), depending on a bug). This is because, while RaceFuzzer precisely interleaves the scheduling at the kernel's instruction level when finding this bug, C repro cannot fully utilize such a feature. Please disregard all code related to "should_hypercall" in the C repro, as this is only for our debugging purposes using our own hypervisor. On Tue, Apr 3, 2018 at 1:12 PM, DaeRyong Jeong wrote: > No. Only the first crash (WARNING in refcount_dec) is reproduced by > the attached reproducer. > > The second crash (kernel bug at af_packet.c:3107) is reproduced by > another reproducer. > We reported it here. > http://lkml.iu.edu/hypermail/linux/kernel/1803.3/05324.html > > On Sun, Apr 1, 2018 at 4:38 PM, Willem de Bruijn > wrote: >> On Thu, Mar 29, 2018 at 1:16 AM, Cong Wang wrote: >>> (Cc'ing netdev and Willem) >>> >>> On Wed, Mar 28, 2018 at 12:03 PM, Byoungyoung Lee >>> wrote: >>>> Another crash patterns observed: race between (setsockopt$packet_int) >>>> and (bind$packet). >>>> >>>> -- >>>> [ 357.731597] kernel BUG at >>>> /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! >>>> [ 357.733382] invalid opcode: [#1] SMP KASAN >>>> [ 357.734017] Modules linked in: >>>> [ 357.734662] CPU: 1 PID: 3871 Comm: repro.exe Not tainted 4.16.0-rc3 #1 >>>> [ 357.735791] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), >>>> BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 >>>> [ 357.737434] RIP: 0010:packet_do_bind+0x88d/0x950 >>>> [ 357.738121] RSP: 0018:8800b2787b08 EFLAGS: 00010293 >>>> [ 357.738906] RAX: 8800b2fdc780 RBX: 880234358cc0 RCX: >>>> 838b244c >>>> [ 357.739905] RDX: RSI: 838b257d RDI: >>>> 0001 >>>> [ 357.741315] RBP: 8800b2787c10 R08: 8800b2fdc780 R09: >>>> >>>> [ 357.743055] R10: 0001 R11: R12: >>>> 88023352ecc0 >>>> [ 357.744744] R13: 0
Re: WARNING in refcount_dec
No. Only the first crash (WARNING in refcount_dec) is reproduced by the attached reproducer. The second crash (kernel bug at af_packet.c:3107) is reproduced by another reproducer. We reported it here. http://lkml.iu.edu/hypermail/linux/kernel/1803.3/05324.html On Sun, Apr 1, 2018 at 4:38 PM, Willem de Bruijnwrote: > On Thu, Mar 29, 2018 at 1:16 AM, Cong Wang wrote: >> (Cc'ing netdev and Willem) >> >> On Wed, Mar 28, 2018 at 12:03 PM, Byoungyoung Lee >> wrote: >>> Another crash patterns observed: race between (setsockopt$packet_int) >>> and (bind$packet). >>> >>> -- >>> [ 357.731597] kernel BUG at >>> /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! >>> [ 357.733382] invalid opcode: [#1] SMP KASAN >>> [ 357.734017] Modules linked in: >>> [ 357.734662] CPU: 1 PID: 3871 Comm: repro.exe Not tainted 4.16.0-rc3 #1 >>> [ 357.735791] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), >>> BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 >>> [ 357.737434] RIP: 0010:packet_do_bind+0x88d/0x950 >>> [ 357.738121] RSP: 0018:8800b2787b08 EFLAGS: 00010293 >>> [ 357.738906] RAX: 8800b2fdc780 RBX: 880234358cc0 RCX: >>> 838b244c >>> [ 357.739905] RDX: RSI: 838b257d RDI: >>> 0001 >>> [ 357.741315] RBP: 8800b2787c10 R08: 8800b2fdc780 R09: >>> >>> [ 357.743055] R10: 0001 R11: R12: >>> 88023352ecc0 >>> [ 357.744744] R13: R14: 0001 R15: >>> 1d00 >>> [ 357.746377] FS: 7f4b43733700() GS:8800b8b0() >>> knlGS: >>> [ 357.749599] CS: 0010 DS: ES: CR0: 80050033 >>> [ 357.752096] CR2: 20058000 CR3: 0002334b8000 CR4: >>> 06e0 >>> [ 357.755045] Call Trace: >>> [ 357.755822] ? compat_packet_setsockopt+0x100/0x100 >>> [ 357.757324] ? __sanitizer_cov_trace_const_cmp8+0x18/0x20 >>> [ 357.758810] packet_bind+0xa2/0xe0 >>> [ 357.759640] SYSC_bind+0x279/0x2f0 >>> [ 357.760364] ? move_addr_to_kernel.part.19+0xc0/0xc0 >>> [ 357.761491] ? __handle_mm_fault+0x25d0/0x25d0 >>> [ 357.762449] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.763663] ? __do_page_fault+0x417/0xba0 >>> [ 357.764569] ? vmalloc_fault+0x910/0x910 >>> [ 357.765405] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.766525] ? mark_held_locks+0x25/0xb0 >>> [ 357.767336] ? SyS_socketpair+0x4a0/0x4a0 >>> [ 357.768182] SyS_bind+0x24/0x30 >>> [ 357.768851] do_syscall_64+0x209/0x5d0 >>> [ 357.769650] ? syscall_return_slowpath+0x3e0/0x3e0 >>> [ 357.770665] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.771779] ? syscall_return_slowpath+0x260/0x3e0 >>> [ 357.772748] ? mark_held_locks+0x25/0xb0 >>> [ 357.773581] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.774720] ? retint_user+0x18/0x18 >>> [ 357.775493] ? trace_hardirqs_off_caller+0xb5/0x120 >>> [ 357.776567] ? trace_hardirqs_off_thunk+0x1a/0x1c >>> [ 357.777512] entry_SYSCALL_64_after_hwframe+0x42/0xb7 >>> [ 357.778508] RIP: 0033:0x4503a9 >>> [ 357.779156] RSP: 002b:7f4b43732ce8 EFLAGS: 0246 ORIG_RAX: >>> 0031 >>> [ 357.780737] RAX: ffda RBX: RCX: >>> 004503a9 >>> [ 357.782169] RDX: 0014 RSI: 20058000 RDI: >>> 0003 >>> [ 357.783710] RBP: 7f4b43732d10 R08: R09: >>> >>> [ 357.785202] R10: R11: 0246 R12: >>> >>> [ 357.786664] R13: R14: 7f4b437339c0 R15: >>> 7f4b43733700 >>> [ 357.788210] Code: c0 fd 48 c7 c2 00 c8 d9 84 be ab 02 00 00 48 c7 >>> c7 60 c8 d9 84 c6 05 e7 a2 48 02 01 e8 3f 17 af fd e9 60 fb ff ff e8 >>> 43 b3 c0 fd <0f> 0b e8 3c b3 c0 fd 48 8b bd 20 ff ff ff e8 60 1e e7 fd >>> 4c 89 >>> [ 357.792260] RIP: packet_do_bind+0x88d/0x950 RSP: 8800b2787b08 >>> [ 357.793698] ---[ end trace 0c5a2539f0247369 ]--- >>> [ 357.794696] Kernel panic - not syncing: Fatal exception >>> [ 357.795918] Kernel Offset: disabled >>> [ 357.796614] Rebooting in 86400 seconds.. >>> >>> On Wed, Mar 28, 2018 at 1:19 AM, Byoungyoung Lee >>> wrote: We report the crash: WARNING in refcount_dec This crash has been found in v4.16-rc3 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, (setsockopt$packet_int) and (setsockopt$packet_rx_ring). C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/repro-refcount_dec.c kernel config: https://kiwi.cs.purdue.edu/static/race-fuzzer/kernel-config-v4.16-rc3 >> >> >> I tried your
Re: WARNING in refcount_dec
No. Only the first crash (WARNING in refcount_dec) is reproduced by the attached reproducer. The second crash (kernel bug at af_packet.c:3107) is reproduced by another reproducer. We reported it here. http://lkml.iu.edu/hypermail/linux/kernel/1803.3/05324.html On Sun, Apr 1, 2018 at 4:38 PM, Willem de Bruijn wrote: > On Thu, Mar 29, 2018 at 1:16 AM, Cong Wang wrote: >> (Cc'ing netdev and Willem) >> >> On Wed, Mar 28, 2018 at 12:03 PM, Byoungyoung Lee >> wrote: >>> Another crash patterns observed: race between (setsockopt$packet_int) >>> and (bind$packet). >>> >>> -- >>> [ 357.731597] kernel BUG at >>> /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! >>> [ 357.733382] invalid opcode: [#1] SMP KASAN >>> [ 357.734017] Modules linked in: >>> [ 357.734662] CPU: 1 PID: 3871 Comm: repro.exe Not tainted 4.16.0-rc3 #1 >>> [ 357.735791] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), >>> BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 >>> [ 357.737434] RIP: 0010:packet_do_bind+0x88d/0x950 >>> [ 357.738121] RSP: 0018:8800b2787b08 EFLAGS: 00010293 >>> [ 357.738906] RAX: 8800b2fdc780 RBX: 880234358cc0 RCX: >>> 838b244c >>> [ 357.739905] RDX: RSI: 838b257d RDI: >>> 0001 >>> [ 357.741315] RBP: 8800b2787c10 R08: 8800b2fdc780 R09: >>> >>> [ 357.743055] R10: 0001 R11: R12: >>> 88023352ecc0 >>> [ 357.744744] R13: R14: 0001 R15: >>> 1d00 >>> [ 357.746377] FS: 7f4b43733700() GS:8800b8b0() >>> knlGS: >>> [ 357.749599] CS: 0010 DS: ES: CR0: 80050033 >>> [ 357.752096] CR2: 20058000 CR3: 0002334b8000 CR4: >>> 06e0 >>> [ 357.755045] Call Trace: >>> [ 357.755822] ? compat_packet_setsockopt+0x100/0x100 >>> [ 357.757324] ? __sanitizer_cov_trace_const_cmp8+0x18/0x20 >>> [ 357.758810] packet_bind+0xa2/0xe0 >>> [ 357.759640] SYSC_bind+0x279/0x2f0 >>> [ 357.760364] ? move_addr_to_kernel.part.19+0xc0/0xc0 >>> [ 357.761491] ? __handle_mm_fault+0x25d0/0x25d0 >>> [ 357.762449] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.763663] ? __do_page_fault+0x417/0xba0 >>> [ 357.764569] ? vmalloc_fault+0x910/0x910 >>> [ 357.765405] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.766525] ? mark_held_locks+0x25/0xb0 >>> [ 357.767336] ? SyS_socketpair+0x4a0/0x4a0 >>> [ 357.768182] SyS_bind+0x24/0x30 >>> [ 357.768851] do_syscall_64+0x209/0x5d0 >>> [ 357.769650] ? syscall_return_slowpath+0x3e0/0x3e0 >>> [ 357.770665] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.771779] ? syscall_return_slowpath+0x260/0x3e0 >>> [ 357.772748] ? mark_held_locks+0x25/0xb0 >>> [ 357.773581] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 >>> [ 357.774720] ? retint_user+0x18/0x18 >>> [ 357.775493] ? trace_hardirqs_off_caller+0xb5/0x120 >>> [ 357.776567] ? trace_hardirqs_off_thunk+0x1a/0x1c >>> [ 357.777512] entry_SYSCALL_64_after_hwframe+0x42/0xb7 >>> [ 357.778508] RIP: 0033:0x4503a9 >>> [ 357.779156] RSP: 002b:7f4b43732ce8 EFLAGS: 0246 ORIG_RAX: >>> 0031 >>> [ 357.780737] RAX: ffda RBX: RCX: >>> 004503a9 >>> [ 357.782169] RDX: 0014 RSI: 20058000 RDI: >>> 0003 >>> [ 357.783710] RBP: 7f4b43732d10 R08: R09: >>> >>> [ 357.785202] R10: R11: 0246 R12: >>> >>> [ 357.786664] R13: R14: 7f4b437339c0 R15: >>> 7f4b43733700 >>> [ 357.788210] Code: c0 fd 48 c7 c2 00 c8 d9 84 be ab 02 00 00 48 c7 >>> c7 60 c8 d9 84 c6 05 e7 a2 48 02 01 e8 3f 17 af fd e9 60 fb ff ff e8 >>> 43 b3 c0 fd <0f> 0b e8 3c b3 c0 fd 48 8b bd 20 ff ff ff e8 60 1e e7 fd >>> 4c 89 >>> [ 357.792260] RIP: packet_do_bind+0x88d/0x950 RSP: 8800b2787b08 >>> [ 357.793698] ---[ end trace 0c5a2539f0247369 ]--- >>> [ 357.794696] Kernel panic - not syncing: Fatal exception >>> [ 357.795918] Kernel Offset: disabled >>> [ 357.796614] Rebooting in 86400 seconds.. >>> >>> On Wed, Mar 28, 2018 at 1:19 AM, Byoungyoung Lee >>> wrote: We report the crash: WARNING in refcount_dec This crash has been found in v4.16-rc3 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, (setsockopt$packet_int) and (setsockopt$packet_rx_ring). C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/repro-refcount_dec.c kernel config: https://kiwi.cs.purdue.edu/static/race-fuzzer/kernel-config-v4.16-rc3 >> >> >> I tried your reproducer, no luck here. >> > > Are both crashes with the same reproducer? > > It races setsockopt PACKET_RX_RING
kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE!
We report the crash: kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE! This crash has been found in v4.16-rc3 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, (setsockopt$packet_int) and (bind$packet). We have confirmed that the kernel v4.16-rc3, v4.16-rc7, and v4.15.14 built with gcc 7.1.0 are crashing by running the provided C repro program within a few minutes (5 minutes). Note that this crash can be triggered from the user space. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c kernel config v4.16-rc3 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config kernel config v4.16-rc7 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config kernel config v4.15.14 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config [ 881.047513] [ cut here ] [ 881.048416] kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! [ 881.050014] invalid opcode: [#1] SMP KASAN [ 881.050698] Dumping ftrace buffer: [ 881.051244](ftrace buffer empty) [ 881.051768] Modules linked in: [ 881.052236] CPU: 1 PID: 18247 Comm: syz-executor0 Not tainted 4.16.0-rc3 #1 [ 881.053247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 [ 881.054880] RIP: 0010:packet_do_bind+0x88d/0x950 [ 881.03] RSP: 0018:8802231d7b08 EFLAGS: 00010212 [ 881.056310] RAX: 0001 RBX: 8800af831740 RCX: c900025ce000 [ 881.057318] RDX: 00a5 RSI: 838b257d RDI: 0001 [ 881.058301] RBP: 8802231d7c10 R08: 8802342f2480 R09: [ 881.059298] R10: 0001 R11: R12: 8802309f8f00 [ 881.060314] R13: R14: 0001 R15: 1000 [ 881.061320] FS: 7f7fab50d700() GS:88023fc0() knlGS: [ 881.062467] CS: 0010 DS: ES: CR0: 80050033 [ 881.063285] CR2: 20038000 CR3: b11c9000 CR4: 06e0 [ 881.064317] Call Trace: [ 881.064686] ? compat_packet_setsockopt+0x100/0x100 [ 881.065430] ? __sanitizer_cov_trace_const_cmp8+0x18/0x20 [ 881.066188] packet_bind+0xa2/0xe0 [ 881.066690] SYSC_bind+0x279/0x2f0 [ 881.067180] ? move_addr_to_kernel.part.19+0xc0/0xc0 [ 881.067896] ? do_futex+0x1e90/0x1e90 [ 881.068435] ? SyS_sched_getaffinity+0xe3/0x100 [ 881.069112] ? mark_held_locks+0x25/0xb0 [ 881.069677] ? SyS_socketpair+0x4a0/0x4a0 [ 881.070265] SyS_bind+0x24/0x30 [ 881.070732] do_syscall_64+0x209/0x5d0 [ 881.071270] ? syscall_return_slowpath+0x3e0/0x3e0 [ 881.071929] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 [ 881.072675] ? syscall_return_slowpath+0x260/0x3e0 [ 881.073365] ? mark_held_locks+0x25/0xb0 [ 881.073950] ? entry_SYSCALL_64_after_hwframe+0x52/0xb7 [ 881.074693] ? trace_hardirqs_off_caller+0xb5/0x120 [ 881.075390] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 881.076079] entry_SYSCALL_64_after_hwframe+0x42/0xb7 [ 881.076797] RIP: 0033:0x453909 [ 881.077238] RSP: 002b:7f7fab50caf8 EFLAGS: 0212 ORIG_RAX: 0031 [ 881.078268] RAX: ffda RBX: 007080d8 RCX: 00453909 [ 881.079239] RDX: 0014 RSI: 2001f000 RDI: 0015 [ 881.080268] RBP: 0250 R08: R09: [ 881.081256] R10: R11: 0212 R12: 004a82d3 [ 881.082272] R13: R14: 0015 R15: 2001f000 [ 881.083251] Code: c0 fd 48 c7 c2 00 c8 d9 84 be ab 02 00 00 48 c7 c7 60 c8 d9 84 c6 05 e7 a2 48 02 01 e8 3f 17 af fd e9 60 fb ff ff e8 43 b3 c0 fd <0f> 0b e8 3c b3 c0 fd 48 8b bd 20 ff ff ff e8 60 1e e7 fd 4c 89 [ 881.085828] RIP: packet_do_bind+0x88d/0x950 RSP: 8802231d7b08 [ 881.086619] ---[ end trace 9c461502752b4f3e ]--- [ 881.087181] Kernel panic - not syncing: Fatal exception [ 881.088352] Dumping ftrace buffer: [ 881.088877](ftrace buffer empty) [ 881.089414] Kernel Offset: disabled [ 881.089950] Rebooting in 86400 seconds.. = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in
kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE!
We report the crash: kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:LINE! This crash has been found in v4.16-rc3 using RaceFuzzer (a modified version of Syzkaller), which we describe more at the end of this report. Our analysis shows that the race occurs when invoking two syscalls concurrently, (setsockopt$packet_int) and (bind$packet). We have confirmed that the kernel v4.16-rc3, v4.16-rc7, and v4.15.14 built with gcc 7.1.0 are crashing by running the provided C repro program within a few minutes (5 minutes). Note that this crash can be triggered from the user space. C repro code : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-repro.c kernel config v4.16-rc3 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc3.config kernel config v4.16-rc7 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.16-rc7.config kernel config v4.15.14 : https://kiwi.cs.purdue.edu/static/race-fuzzer/afpacket-setsockopt-bind-v4.15.14.config [ 881.047513] [ cut here ] [ 881.048416] kernel BUG at /home/blee/project/race-fuzzer/kernels/kernel_v4.16-rc3/net/packet/af_packet.c:3107! [ 881.050014] invalid opcode: [#1] SMP KASAN [ 881.050698] Dumping ftrace buffer: [ 881.051244](ftrace buffer empty) [ 881.051768] Modules linked in: [ 881.052236] CPU: 1 PID: 18247 Comm: syz-executor0 Not tainted 4.16.0-rc3 #1 [ 881.053247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 [ 881.054880] RIP: 0010:packet_do_bind+0x88d/0x950 [ 881.03] RSP: 0018:8802231d7b08 EFLAGS: 00010212 [ 881.056310] RAX: 0001 RBX: 8800af831740 RCX: c900025ce000 [ 881.057318] RDX: 00a5 RSI: 838b257d RDI: 0001 [ 881.058301] RBP: 8802231d7c10 R08: 8802342f2480 R09: [ 881.059298] R10: 0001 R11: R12: 8802309f8f00 [ 881.060314] R13: R14: 0001 R15: 1000 [ 881.061320] FS: 7f7fab50d700() GS:88023fc0() knlGS: [ 881.062467] CS: 0010 DS: ES: CR0: 80050033 [ 881.063285] CR2: 20038000 CR3: b11c9000 CR4: 06e0 [ 881.064317] Call Trace: [ 881.064686] ? compat_packet_setsockopt+0x100/0x100 [ 881.065430] ? __sanitizer_cov_trace_const_cmp8+0x18/0x20 [ 881.066188] packet_bind+0xa2/0xe0 [ 881.066690] SYSC_bind+0x279/0x2f0 [ 881.067180] ? move_addr_to_kernel.part.19+0xc0/0xc0 [ 881.067896] ? do_futex+0x1e90/0x1e90 [ 881.068435] ? SyS_sched_getaffinity+0xe3/0x100 [ 881.069112] ? mark_held_locks+0x25/0xb0 [ 881.069677] ? SyS_socketpair+0x4a0/0x4a0 [ 881.070265] SyS_bind+0x24/0x30 [ 881.070732] do_syscall_64+0x209/0x5d0 [ 881.071270] ? syscall_return_slowpath+0x3e0/0x3e0 [ 881.071929] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20 [ 881.072675] ? syscall_return_slowpath+0x260/0x3e0 [ 881.073365] ? mark_held_locks+0x25/0xb0 [ 881.073950] ? entry_SYSCALL_64_after_hwframe+0x52/0xb7 [ 881.074693] ? trace_hardirqs_off_caller+0xb5/0x120 [ 881.075390] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 881.076079] entry_SYSCALL_64_after_hwframe+0x42/0xb7 [ 881.076797] RIP: 0033:0x453909 [ 881.077238] RSP: 002b:7f7fab50caf8 EFLAGS: 0212 ORIG_RAX: 0031 [ 881.078268] RAX: ffda RBX: 007080d8 RCX: 00453909 [ 881.079239] RDX: 0014 RSI: 2001f000 RDI: 0015 [ 881.080268] RBP: 0250 R08: R09: [ 881.081256] R10: R11: 0212 R12: 004a82d3 [ 881.082272] R13: R14: 0015 R15: 2001f000 [ 881.083251] Code: c0 fd 48 c7 c2 00 c8 d9 84 be ab 02 00 00 48 c7 c7 60 c8 d9 84 c6 05 e7 a2 48 02 01 e8 3f 17 af fd e9 60 fb ff ff e8 43 b3 c0 fd <0f> 0b e8 3c b3 c0 fd 48 8b bd 20 ff ff ff e8 60 1e e7 fd 4c 89 [ 881.085828] RIP: packet_do_bind+0x88d/0x950 RSP: 8802231d7b08 [ 881.086619] ---[ end trace 9c461502752b4f3e ]--- [ 881.087181] Kernel panic - not syncing: Fatal exception [ 881.088352] Dumping ftrace buffer: [ 881.088877](ftrace buffer empty) [ 881.089414] Kernel Offset: disabled [ 881.089950] Rebooting in 86400 seconds.. = About RaceFuzzer RaceFuzzer is a customized version of Syzkaller, specifically tailored to find race condition bugs in the Linux kernel. While we leverage many different technique, the notable feature of RaceFuzzer is in leveraging a custom hypervisor (QEMU/KVM) to interleave the scheduling. In particular, we modified the hypervisor to intentionally stall a per-core execution, which is similar to supporting per-core breakpoint functionality. This allows RaceFuzzer to force the kernel to deterministically trigger racy condition (which may rarely happen in practice due to randomness in