linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
@ 2025-07-19 17:29 syzbot
  2025-07-20  0:36 ` Hillf Danton
                   ` (4 more replies)
  0 siblings, 5 replies; 26+ messages in thread
From: syzbot @ 2025-07-19 17:29 UTC (permalink / raw)
  To: axboe, io-uring, linux-kernel, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000

Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com

==================================================================
BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339

CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Workqueue: events io_fallback_req_func
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0xcd/0x610 mm/kasan/report.c:480
 kasan_report+0xe0/0x110 mm/kasan/report.c:593
 __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
 kasan_check_byte include/linux/kasan.h:399 [inline]
 lock_acquire kernel/locking/lockdep.c:5845 [inline]
 lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
 __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
 _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
 spin_lock_irq include/linux/spinlock.h:376 [inline]
 io_poll_remove_entry io_uring/poll.c:146 [inline]
 io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
 io_poll_remove_entries io_uring/poll.c:159 [inline]
 io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
 io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
 process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
 process_scheduled_works kernel/workqueue.c:3321 [inline]
 worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
 kthread+0x3c5/0x780 kernel/kthread.c:464
 ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

Allocated by task 6154:
 kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
 kasan_save_track+0x14/0x30 mm/kasan/common.c:68
 poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
 __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
 kmalloc_noprof include/linux/slab.h:905 [inline]
 kzalloc_noprof include/linux/slab.h:1039 [inline]
 __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
 __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
 comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
 comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
 do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
 comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:907 [inline]
 __se_sys_ioctl fs/ioctl.c:893 [inline]
 __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Freed by task 6156:
 kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
 kasan_save_track+0x14/0x30 mm/kasan/common.c:68
 kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
 poison_slab_object mm/kasan/common.c:247 [inline]
 __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
 kasan_slab_free include/linux/kasan.h:233 [inline]
 slab_free_hook mm/slub.c:2381 [inline]
 slab_free mm/slub.c:4643 [inline]
 kfree+0x2b4/0x4d0 mm/slub.c:4842
 comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
 comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
 do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
 comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:907 [inline]
 __se_sys_ioctl fs/ioctl.c:893 [inline]
 __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff88803c6f4200
 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 176 bytes inside of
 freed 256-byte region [ffff88803c6f4200, ffff88803c6f4300)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3c6f4
head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000040 ffff88801b842b40 ffffea0000f0c180 dead000000000004
raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 00fff00000000040 ffff88801b842b40 ffffea0000f0c180 dead000000000004
head: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 00fff00000000001 ffffea0000f1bd01 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 6018, tgid 6018 (syz-executor), ts 49909540314, free_ts 49907641430
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x1c0/0x230 mm/page_alloc.c:1704
 prep_new_page mm/page_alloc.c:1712 [inline]
 get_page_from_freelist+0x1321/0x3890 mm/page_alloc.c:3669
 __alloc_frozen_pages_noprof+0x261/0x23f0 mm/page_alloc.c:4959
 alloc_pages_mpol+0x1fb/0x550 mm/mempolicy.c:2419
 alloc_slab_page mm/slub.c:2451 [inline]
 allocate_slab mm/slub.c:2619 [inline]
 new_slab+0x23b/0x330 mm/slub.c:2673
 ___slab_alloc+0xd9c/0x1940 mm/slub.c:3859
 __slab_alloc.constprop.0+0x56/0xb0 mm/slub.c:3949
 __slab_alloc_node mm/slub.c:4024 [inline]
 slab_alloc_node mm/slub.c:4185 [inline]
 __do_kmalloc_node mm/slub.c:4327 [inline]
 __kmalloc_node_track_caller_noprof+0x2ee/0x510 mm/slub.c:4347
 kmemdup_noprof+0x29/0x60 mm/util.c:137
 ipt_register_table+0x224/0x430 net/ipv4/netfilter/ip_tables.c:1770
 iptable_filter_table_init+0x75/0xa0 net/ipv4/netfilter/iptable_filter.c:49
 xt_find_table_lock+0x2e4/0x520 net/netfilter/x_tables.c:1260
 xt_request_find_table_lock+0x28/0xf0 net/netfilter/x_tables.c:1285
 get_info+0x19c/0x7c0 net/ipv4/netfilter/ip_tables.c:963
 do_ipt_get_ctl+0x169/0xaa0 net/ipv4/netfilter/ip_tables.c:1659
 nf_getsockopt+0x7c/0xe0 net/netfilter/nf_sockopt.c:116
page last free pid 6018 tgid 6018 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 free_pages_prepare mm/page_alloc.c:1248 [inline]
 __free_frozen_pages+0x7fe/0x1180 mm/page_alloc.c:2706
 qlink_free mm/kasan/quarantine.c:163 [inline]
 qlist_free_all+0x4d/0x120 mm/kasan/quarantine.c:179
 kasan_quarantine_reduce+0x195/0x1e0 mm/kasan/quarantine.c:286
 __kasan_slab_alloc+0x69/0x90 mm/kasan/common.c:329
 kasan_slab_alloc include/linux/kasan.h:250 [inline]
 slab_post_alloc_hook mm/slub.c:4148 [inline]
 slab_alloc_node mm/slub.c:4197 [inline]
 kmem_cache_alloc_noprof+0x1cb/0x3b0 mm/slub.c:4204
 getname_flags.part.0+0x4c/0x550 fs/namei.c:146
 getname_flags+0x93/0xf0 include/linux/audit.h:322
 getname include/linux/fs.h:2907 [inline]
 __do_sys_mkdirat fs/namei.c:4425 [inline]
 __se_sys_mkdirat fs/namei.c:4423 [inline]
 __x64_sys_mkdirat+0x76/0xb0 fs/namei.c:4423
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Memory state around the buggy address:
 ffff88803c6f4180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88803c6f4200: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88803c6f4280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                     ^
 ffff88803c6f4300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88803c6f4380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
@ 2025-07-20  0:36 ` Hillf Danton
  2025-07-20  0:49   ` syzbot
  2025-07-20  1:12 ` Hillf Danton
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 26+ messages in thread
From: Hillf Danton @ 2025-07-20  0:36 UTC (permalink / raw)
  To: syzbot; +Cc: axboe, io-uring, linux-kernel, syzkaller-bugs

> Date: Sat, 19 Jul 2025 10:29:34 -0700	[thread overview]
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000

What is difficult to understand is why rcu failed to prevent the uaf.

#syz test

--- x/io_uring/poll.c
+++ y/io_uring/poll.c
@@ -143,6 +143,8 @@ static inline void io_poll_remove_entry(
 	struct wait_queue_head *head = smp_load_acquire(&poll->head);
 
 	if (head) {
+		if (list_empty(&poll->wait.entry))
+			return;
 		spin_lock_irq(&head->lock);
 		list_del_init(&poll->wait.entry);
 		poll->head = NULL;
@@ -416,7 +418,7 @@ static int io_poll_wake(struct wait_queu
 		/* optional, saves extra locking for removal in tw handler */
 		if (mask && poll->events & EPOLLONESHOT) {
 			list_del_init(&poll->wait.entry);
-			poll->head = NULL;
+			smp_store_release(&poll->head, NULL);
 			if (wqe_is_double(wait))
 				req->flags &= ~REQ_F_DOUBLE_POLL;
 			else
--

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20  0:36 ` Hillf Danton
@ 2025-07-20  0:49   ` syzbot
  0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-07-20  0:49 UTC (permalink / raw)
  To: axboe, hdanton, io-uring, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
KASAN: slab-use-after-free Read in io_poll_remove_entries

==================================================================
BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
Read of size 1 at addr ffff888025296ab0 by task kworker/0:2/837

CPU: 0 UID: 0 PID: 837 Comm: kworker/0:2 Not tainted 6.16.0-rc6-syzkaller-00281-gf4a40a4282f4-dirty #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Workqueue: events io_fallback_req_func
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0xcd/0x610 mm/kasan/report.c:480
 kasan_report+0xe0/0x110 mm/kasan/report.c:593
 __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
 kasan_check_byte include/linux/kasan.h:399 [inline]
 lock_acquire kernel/locking/lockdep.c:5845 [inline]
 lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
 __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
 _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
 spin_lock_irq include/linux/spinlock.h:376 [inline]
 io_poll_remove_entry io_uring/poll.c:148 [inline]
 io_poll_remove_entries.part.0+0x17b/0x850 io_uring/poll.c:181
 io_poll_remove_entries io_uring/poll.c:161 [inline]
 io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:328
 io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
 process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
 process_scheduled_works kernel/workqueue.c:3321 [inline]
 worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
 kthread+0x3c5/0x780 kernel/kthread.c:464
 ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

Allocated by task 6579:
 kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
 kasan_save_track+0x14/0x30 mm/kasan/common.c:68
 poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
 __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
 kmalloc_noprof include/linux/slab.h:905 [inline]
 kzalloc_noprof include/linux/slab.h:1039 [inline]
 __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
 __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
 comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
 comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
 do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
 comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:907 [inline]
 __se_sys_ioctl fs/ioctl.c:893 [inline]
 __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Freed by task 6581:
 kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
 kasan_save_track+0x14/0x30 mm/kasan/common.c:68
 kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
 poison_slab_object mm/kasan/common.c:247 [inline]
 __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
 kasan_slab_free include/linux/kasan.h:233 [inline]
 slab_free_hook mm/slub.c:2381 [inline]
 slab_free mm/slub.c:4643 [inline]
 kfree+0x2b4/0x4d0 mm/slub.c:4842
 comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
 comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
 do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
 comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:907 [inline]
 __se_sys_ioctl fs/ioctl.c:893 [inline]
 __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff888025296a00
 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 176 bytes inside of
 freed 256-byte region [ffff888025296a00, ffff888025296b00)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x25296
head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000040 ffff88801b842b40 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 00fff00000000040 ffff88801b842b40 dead000000000122 0000000000000000
head: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 00fff00000000001 ffffea000094a581 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 1, migratetype Unmovable, gfp_mask 0x252800(GFP_NOWAIT|__GFP_NORETRY|__GFP_COMP|__GFP_THISNODE), pid 6279, tgid 6279 (udevd), ts 91681288326, free_ts 91422215520
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x1c0/0x230 mm/page_alloc.c:1704
 prep_new_page mm/page_alloc.c:1712 [inline]
 get_page_from_freelist+0x1321/0x3890 mm/page_alloc.c:3669
 __alloc_frozen_pages_noprof+0x261/0x23f0 mm/page_alloc.c:4959
 alloc_slab_page mm/slub.c:2453 [inline]
 allocate_slab mm/slub.c:2619 [inline]
 new_slab+0x94/0x330 mm/slub.c:2673
 ___slab_alloc+0xd9c/0x1940 mm/slub.c:3859
 __slab_alloc.constprop.0+0x56/0xb0 mm/slub.c:3949
 __slab_alloc_node mm/slub.c:4024 [inline]
 slab_alloc_node mm/slub.c:4185 [inline]
 __do_kmalloc_node mm/slub.c:4327 [inline]
 __kmalloc_node_noprof+0x2ed/0x500 mm/slub.c:4334
 kmalloc_array_node_noprof include/linux/slab.h:1020 [inline]
 alloc_slab_obj_exts+0x41/0xa0 mm/slub.c:1992
 account_slab mm/slub.c:2578 [inline]
 allocate_slab mm/slub.c:2638 [inline]
 new_slab+0x283/0x330 mm/slub.c:2673
 ___slab_alloc+0xd9c/0x1940 mm/slub.c:3859
 __slab_alloc.constprop.0+0x56/0xb0 mm/slub.c:3949
 __slab_alloc_node mm/slub.c:4024 [inline]
 slab_alloc_node mm/slub.c:4185 [inline]
 __do_kmalloc_node mm/slub.c:4327 [inline]
 __kvmalloc_node_noprof+0x3b1/0x620 mm/slub.c:5015
 simple_xattr_alloc+0x41/0xa0 fs/xattr.c:1238
 simple_xattr_set+0x3d/0x3e0 fs/xattr.c:1358
 shmem_xattr_handler_set+0x31b/0x3b0 mm/shmem.c:4331
 __vfs_setxattr+0x172/0x1e0 fs/xattr.c:200
page last free pid 33 tgid 33 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 free_pages_prepare mm/page_alloc.c:1248 [inline]
 __free_frozen_pages+0x7fe/0x1180 mm/page_alloc.c:2706
 rcu_do_batch kernel/rcu/tree.c:2576 [inline]
 rcu_core+0x799/0x14e0 kernel/rcu/tree.c:2832
 handle_softirqs+0x219/0x8e0 kernel/softirq.c:579
 run_ksoftirqd kernel/softirq.c:968 [inline]
 run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960
 smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:164
 kthread+0x3c5/0x780 kernel/kthread.c:464
 ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Memory state around the buggy address:
 ffff888025296980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888025296a00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888025296a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                     ^
 ffff888025296b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888025296b80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


Tested on:

commit:         f4a40a42 Merge tag 'efi-fixes-for-v6.16-2' of git://gi..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=110104f0580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=1799138c580000


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
  2025-07-20  0:36 ` Hillf Danton
@ 2025-07-20  1:12 ` Hillf Danton
  2025-07-20  1:31   ` syzbot
  2025-07-20 18:24 ` Jens Axboe
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 26+ messages in thread
From: Hillf Danton @ 2025-07-20  1:12 UTC (permalink / raw)
  To: syzbot; +Cc: linux-kernel, syzkaller-bugs

> Date: Sat, 19 Jul 2025 10:29:34 -0700	[thread overview]
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000

What is difficult to understand is why rcu failed to prevent the uaf.

#syz test

--- x/include/linux/comedi/comedidev.h
+++ y/include/linux/comedi/comedidev.h
@@ -364,6 +364,7 @@ struct comedi_async {
 	struct comedi_cmd cmd;
 	wait_queue_head_t wait_head;
 	unsigned int cb_mask;
+	struct rcu_head rcu;
 	int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
 		       unsigned int x);
 };
--- l/drivers/comedi/drivers.c
+++ y/drivers/comedi/drivers.c
@@ -168,7 +168,7 @@ static void comedi_device_detach_cleanup
 			comedi_free_subdevice_minor(s);
 			if (s->async) {
 				comedi_buf_alloc(dev, s, 0);
-				kfree(s->async);
+				kfree_rcu(s->async, rcu);
 			}
 			kfree(s->readback);
 		}
--

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20  1:12 ` Hillf Danton
@ 2025-07-20  1:31   ` syzbot
  0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-07-20  1:31 UTC (permalink / raw)
  To: hdanton, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
Tested-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com

Tested on:

commit:         f4a40a42 Merge tag 'efi-fixes-for-v6.16-2' of git://gi..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=130904f0580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=11ab37d4580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
  2025-07-20  0:36 ` Hillf Danton
  2025-07-20  1:12 ` Hillf Danton
@ 2025-07-20 18:24 ` Jens Axboe
  2025-07-20 18:49   ` Jens Axboe
  2025-07-20 18:44 ` Forwarded: " syzbot
  2025-07-22 12:47 ` Jens Axboe
  4 siblings, 1 reply; 26+ messages in thread
From: Jens Axboe @ 2025-07-20 18:24 UTC (permalink / raw)
  To: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten,
	Greg Kroah-Hartman

On 7/19/25 11:29 AM, syzbot wrote:
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
> 
> Downloadable assets:
> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
> 
> ==================================================================
> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
> 
> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
> Workqueue: events io_fallback_req_func
> Call Trace:
>  <TASK>
>  __dump_stack lib/dump_stack.c:94 [inline]
>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>  print_address_description mm/kasan/report.c:378 [inline]
>  print_report+0xcd/0x610 mm/kasan/report.c:480
>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>  kasan_check_byte include/linux/kasan.h:399 [inline]
>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>  kthread+0x3c5/0x780 kernel/kthread.c:464
>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>  </TASK>
> 
> Allocated by task 6154:
>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>  kmalloc_noprof include/linux/slab.h:905 [inline]
>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
> Freed by task 6156:
>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>  poison_slab_object mm/kasan/common.c:247 [inline]
>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>  kasan_slab_free include/linux/kasan.h:233 [inline]
>  slab_free_hook mm/slub.c:2381 [inline]
>  slab_free mm/slub.c:4643 [inline]
>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f

I took a quick look at this, and surely looks like a comedi bug. If you
call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
a detach and frees the device, regardless of whether anyone has it
opened or not?! It's got some odd notion of checking whether it's busy
or not. For this case, someone has a poll active on the device, yet it
still happily frees it.

CC'ing some folks, as this looks utterly broken.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Forwarded: Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
                   ` (2 preceding siblings ...)
  2025-07-20 18:24 ` Jens Axboe
@ 2025-07-20 18:44 ` syzbot
  2025-07-22 12:47 ` Jens Axboe
  4 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-07-20 18:44 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
Author: axboe@kernel.dk

#syz set subsystems: kernel

As per other replies, definitely not an io_uring issue and no comedi
subsystem exists.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 18:24 ` Jens Axboe
@ 2025-07-20 18:49   ` Jens Axboe
  2025-07-20 19:00     ` Jens Axboe
  2025-07-23 14:08     ` Aleksandr Nogikh
  0 siblings, 2 replies; 26+ messages in thread
From: Jens Axboe @ 2025-07-20 18:49 UTC (permalink / raw)
  To: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten,
	Greg Kroah-Hartman

On 7/20/25 12:24 PM, Jens Axboe wrote:
> On 7/19/25 11:29 AM, syzbot wrote:
>> Hello,
>>
>> syzbot found the following issue on:
>>
>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>> git tree:       upstream
>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>
>> Downloadable assets:
>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>
>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>
>> ==================================================================
>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>
>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>> Workqueue: events io_fallback_req_func
>> Call Trace:
>>  <TASK>
>>  __dump_stack lib/dump_stack.c:94 [inline]
>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>  print_address_description mm/kasan/report.c:378 [inline]
>>  print_report+0xcd/0x610 mm/kasan/report.c:480
>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>  kasan_check_byte include/linux/kasan.h:399 [inline]
>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>  kthread+0x3c5/0x780 kernel/kthread.c:464
>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>  </TASK>
>>
>> Allocated by task 6154:
>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>  kmalloc_noprof include/linux/slab.h:905 [inline]
>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>
>> Freed by task 6156:
>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>  poison_slab_object mm/kasan/common.c:247 [inline]
>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>  kasan_slab_free include/linux/kasan.h:233 [inline]
>>  slab_free_hook mm/slub.c:2381 [inline]
>>  slab_free mm/slub.c:4643 [inline]
>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
> I took a quick look at this, and surely looks like a comedi bug. If you
> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
> a detach and frees the device, regardless of whether anyone has it
> opened or not?! It's got some odd notion of checking whether it's busy
> or not. For this case, someone has a poll active on the device, yet it
> still happily frees it.
> 
> CC'ing some folks, as this looks utterly broken.

Case in point, I added:

diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index 376130bfba8a..4d5fde012558 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
 				kfree(s->private);
 			comedi_free_subdevice_minor(s);
 			if (s->async) {
+				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
 				comedi_buf_alloc(dev, s, 0);
 				kfree(s->async);
 			}

and this is the first thing that triggers:

WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
Modules linked in:
CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE 
Hardware name: linux,dummy-virt (DT)
pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
pc : comedi_device_detach+0x510/0x720
lr : comedi_device_detach+0x1dc/0x720
sp : ffff80008aeb7880
x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
Call trace:
 comedi_device_detach+0x510/0x720 (P)
 do_devconfig_ioctl+0x37c/0x4b8
 comedi_unlocked_ioctl+0x33c/0x2bd8
 __arm64_sys_ioctl+0x124/0x1a0
 invoke_syscall.constprop.0+0x60/0x2a0
 el0_svc_common.constprop.0+0x148/0x240
 do_el0_svc+0x40/0x60
 el0_svc+0x44/0xe0
 el0t_64_sync_handler+0x104/0x130
 el0t_64_sync+0x170/0x178

Not sure what the right fix for comedi is here, it'd probably be at
least somewhat saner if it only allowed removal of the device when the
ref count would be 1 (for the ioctl itself). Just ignoring the file ref
and allowing blanket removal seems highly suspicious / broken.

As there's no comedi subsystem in syzbot, moving it to kernel:

#syz set subsystems: kernel

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 18:49   ` Jens Axboe
@ 2025-07-20 19:00     ` Jens Axboe
  2025-07-20 19:19       ` [syzbot] [kernel] " syzbot
                         ` (2 more replies)
  2025-07-23 14:08     ` Aleksandr Nogikh
  1 sibling, 3 replies; 26+ messages in thread
From: Jens Axboe @ 2025-07-20 19:00 UTC (permalink / raw)
  To: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten,
	Greg Kroah-Hartman

On 7/20/25 12:49 PM, Jens Axboe wrote:
> On 7/20/25 12:24 PM, Jens Axboe wrote:
>> On 7/19/25 11:29 AM, syzbot wrote:
>>> Hello,
>>>
>>> syzbot found the following issue on:
>>>
>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>>> git tree:       upstream
>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>
>>> Downloadable assets:
>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>
>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>
>>> ==================================================================
>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>>
>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>>> Workqueue: events io_fallback_req_func
>>> Call Trace:
>>>  <TASK>
>>>  __dump_stack lib/dump_stack.c:94 [inline]
>>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>  print_address_description mm/kasan/report.c:378 [inline]
>>>  print_report+0xcd/0x610 mm/kasan/report.c:480
>>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>  kasan_check_byte include/linux/kasan.h:399 [inline]
>>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>  kthread+0x3c5/0x780 kernel/kthread.c:464
>>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>  </TASK>
>>>
>>> Allocated by task 6154:
>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>  kmalloc_noprof include/linux/slab.h:905 [inline]
>>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>
>>> Freed by task 6156:
>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>  poison_slab_object mm/kasan/common.c:247 [inline]
>>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>  kasan_slab_free include/linux/kasan.h:233 [inline]
>>>  slab_free_hook mm/slub.c:2381 [inline]
>>>  slab_free mm/slub.c:4643 [inline]
>>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>
>> I took a quick look at this, and surely looks like a comedi bug. If you
>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
>> a detach and frees the device, regardless of whether anyone has it
>> opened or not?! It's got some odd notion of checking whether it's busy
>> or not. For this case, someone has a poll active on the device, yet it
>> still happily frees it.
>>
>> CC'ing some folks, as this looks utterly broken.
> 
> Case in point, I added:
> 
> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
> index 376130bfba8a..4d5fde012558 100644
> --- a/drivers/comedi/drivers.c
> +++ b/drivers/comedi/drivers.c
> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>  				kfree(s->private);
>  			comedi_free_subdevice_minor(s);
>  			if (s->async) {
> +				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>  				comedi_buf_alloc(dev, s, 0);
>  				kfree(s->async);
>  			}
> 
> and this is the first thing that triggers:
> 
> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
> Modules linked in:
> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE 
> Hardware name: linux,dummy-virt (DT)
> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
> pc : comedi_device_detach+0x510/0x720
> lr : comedi_device_detach+0x1dc/0x720
> sp : ffff80008aeb7880
> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
> Call trace:
>  comedi_device_detach+0x510/0x720 (P)
>  do_devconfig_ioctl+0x37c/0x4b8
>  comedi_unlocked_ioctl+0x33c/0x2bd8
>  __arm64_sys_ioctl+0x124/0x1a0
>  invoke_syscall.constprop.0+0x60/0x2a0
>  el0_svc_common.constprop.0+0x148/0x240
>  do_el0_svc+0x40/0x60
>  el0_svc+0x44/0xe0
>  el0t_64_sync_handler+0x104/0x130
>  el0t_64_sync+0x170/0x178
> 
> Not sure what the right fix for comedi is here, it'd probably be at
> least somewhat saner if it only allowed removal of the device when the
> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
> and allowing blanket removal seems highly suspicious / broken.
> 
> As there's no comedi subsystem in syzbot, moving it to kernel:
> 
> #syz set subsystems: kernel

Something like the below may help, at least it'll tell us the device is
busy if there's a poll active on it.

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 3383a7ce27ff..ea96bc4b818e 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
 static int is_device_busy(struct comedi_device *dev)
 {
 	struct comedi_subdevice *s;
-	int i;
+	int i, is_busy = 0;
 
 	lockdep_assert_held(&dev->mutex);
 	if (!dev->attached)
 		return 0;
 
+	/* prevent new polls */
+	down_write(&dev->attach_lock);
+
 	for (i = 0; i < dev->n_subdevices; i++) {
 		s = &dev->subdevices[i];
-		if (s->busy)
-			return 1;
-		if (s->async && comedi_buf_is_mmapped(s))
-			return 1;
+		if (s->busy) {
+			is_busy = 1;
+			break;
+		}
+		if (!s->async)
+			continue;
+		if (comedi_buf_is_mmapped(s) ||
+		    waitqueue_active(&s->async->wait_head)) {
+			is_busy = 1;
+			break;
+		}
 	}
-
-	return 0;
+	up_write(&dev->attach_lock);
+	return is_busy;
 }
 
 /*

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [kernel] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 19:00     ` Jens Axboe
@ 2025-07-20 19:19       ` syzbot
  2025-07-22 12:21       ` [syzbot] [io-uring?] " Jens Axboe
  2025-07-22 12:47       ` Ian Abbott
  2 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-07-20 19:19 UTC (permalink / raw)
  To: abbotti, axboe, gregkh, hsweeten, io-uring, linux-kernel,
	syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
Tested-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com

Tested on:

commit:         07fa9cad Merge tag 'x86-urgent-2025-07-20' of git://gi..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1086638c580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=16a8cb82580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 19:00     ` Jens Axboe
  2025-07-20 19:19       ` [syzbot] [kernel] " syzbot
@ 2025-07-22 12:21       ` Jens Axboe
  2025-07-22 12:30         ` Ian Abbott
  2025-07-22 12:31         ` Greg Kroah-Hartman
  2025-07-22 12:47       ` Ian Abbott
  2 siblings, 2 replies; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 12:21 UTC (permalink / raw)
  To: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten,
	Greg Kroah-Hartman

On 7/20/25 1:00 PM, Jens Axboe wrote:
> On 7/20/25 12:49 PM, Jens Axboe wrote:
>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>> Hello,
>>>>
>>>> syzbot found the following issue on:
>>>>
>>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>>>> git tree:       upstream
>>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>
>>>> Downloadable assets:
>>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>
>>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>
>>>> ==================================================================
>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>>>
>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>>>> Workqueue: events io_fallback_req_func
>>>> Call Trace:
>>>>  <TASK>
>>>>  __dump_stack lib/dump_stack.c:94 [inline]
>>>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>  print_address_description mm/kasan/report.c:378 [inline]
>>>>  print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>  kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>  kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>  </TASK>
>>>>
>>>> Allocated by task 6154:
>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>  kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>>>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>>>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>>>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>>>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>
>>>> Freed by task 6156:
>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>  poison_slab_object mm/kasan/common.c:247 [inline]
>>>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>  kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>  slab_free_hook mm/slub.c:2381 [inline]
>>>>  slab_free mm/slub.c:4643 [inline]
>>>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>>>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>>>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>
>>> I took a quick look at this, and surely looks like a comedi bug. If you
>>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
>>> a detach and frees the device, regardless of whether anyone has it
>>> opened or not?! It's got some odd notion of checking whether it's busy
>>> or not. For this case, someone has a poll active on the device, yet it
>>> still happily frees it.
>>>
>>> CC'ing some folks, as this looks utterly broken.
>>
>> Case in point, I added:
>>
>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>> index 376130bfba8a..4d5fde012558 100644
>> --- a/drivers/comedi/drivers.c
>> +++ b/drivers/comedi/drivers.c
>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>>  				kfree(s->private);
>>  			comedi_free_subdevice_minor(s);
>>  			if (s->async) {
>> +				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>  				comedi_buf_alloc(dev, s, 0);
>>  				kfree(s->async);
>>  			}
>>
>> and this is the first thing that triggers:
>>
>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
>> Modules linked in:
>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE 
>> Hardware name: linux,dummy-virt (DT)
>> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>> pc : comedi_device_detach+0x510/0x720
>> lr : comedi_device_detach+0x1dc/0x720
>> sp : ffff80008aeb7880
>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>> Call trace:
>>  comedi_device_detach+0x510/0x720 (P)
>>  do_devconfig_ioctl+0x37c/0x4b8
>>  comedi_unlocked_ioctl+0x33c/0x2bd8
>>  __arm64_sys_ioctl+0x124/0x1a0
>>  invoke_syscall.constprop.0+0x60/0x2a0
>>  el0_svc_common.constprop.0+0x148/0x240
>>  do_el0_svc+0x40/0x60
>>  el0_svc+0x44/0xe0
>>  el0t_64_sync_handler+0x104/0x130
>>  el0t_64_sync+0x170/0x178
>>
>> Not sure what the right fix for comedi is here, it'd probably be at
>> least somewhat saner if it only allowed removal of the device when the
>> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
>> and allowing blanket removal seems highly suspicious / broken.
>>
>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>
>> #syz set subsystems: kernel
> 
> Something like the below may help, at least it'll tell us the device is
> busy if there's a poll active on it.
> 
> #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
> 
> 
> diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
> index 3383a7ce27ff..ea96bc4b818e 100644
> --- a/drivers/comedi/comedi_fops.c
> +++ b/drivers/comedi/comedi_fops.c
> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
>  static int is_device_busy(struct comedi_device *dev)
>  {
>  	struct comedi_subdevice *s;
> -	int i;
> +	int i, is_busy = 0;
>  
>  	lockdep_assert_held(&dev->mutex);
>  	if (!dev->attached)
>  		return 0;
>  
> +	/* prevent new polls */
> +	down_write(&dev->attach_lock);
> +
>  	for (i = 0; i < dev->n_subdevices; i++) {
>  		s = &dev->subdevices[i];
> -		if (s->busy)
> -			return 1;
> -		if (s->async && comedi_buf_is_mmapped(s))
> -			return 1;
> +		if (s->busy) {
> +			is_busy = 1;
> +			break;
> +		}
> +		if (!s->async)
> +			continue;
> +		if (comedi_buf_is_mmapped(s) ||
> +		    waitqueue_active(&s->async->wait_head)) {
> +			is_busy = 1;
> +			break;
> +		}
>  	}
> -
> -	return 0;
> +	up_write(&dev->attach_lock);
> +	return is_busy;
>  }
>  
>  /*

Haven't heard anything back, so I guess I'll send it out as a patch?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:21       ` [syzbot] [io-uring?] " Jens Axboe
@ 2025-07-22 12:30         ` Ian Abbott
  2025-07-22 12:43           ` Jens Axboe
  2025-07-22 12:31         ` Greg Kroah-Hartman
  1 sibling, 1 reply; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 12:30 UTC (permalink / raw)
  To: Jens Axboe, syzbot, io-uring, linux-kernel, syzkaller-bugs,
	hsweeten, Greg Kroah-Hartman

On 22/07/2025 13:21, Jens Axboe wrote:
> On 7/20/25 1:00 PM, Jens Axboe wrote:
>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>>> Hello,
>>>>>
>>>>> syzbot found the following issue on:
>>>>>
>>>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>>>>> git tree:       upstream
>>>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>>>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>>>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>>>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>
>>>>> Downloadable assets:
>>>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>
>>>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>>>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>
>>>>> ==================================================================
>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>
>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>>>>> Workqueue: events io_fallback_req_func
>>>>> Call Trace:
>>>>>   <TASK>
>>>>>   __dump_stack lib/dump_stack.c:94 [inline]
>>>>>   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>   print_address_description mm/kasan/report.c:378 [inline]
>>>>>   print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>   kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>   __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>   kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>   lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>   lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>   __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>   _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>   spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>>   io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>>   io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>   io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>   io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>   io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>   process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>   process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>   worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>   kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>   ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>   </TASK>
>>>>>
>>>>> Allocated by task 6154:
>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>   poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>   __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>   kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>   kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>   __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>>>>   __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>>>>   comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>>>>   comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>>>>   do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>>>>   comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>   vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>   __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>   __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>   __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> Freed by task 6156:
>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>   kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>   poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>   __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>   kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>   slab_free_hook mm/slub.c:2381 [inline]
>>>>>   slab_free mm/slub.c:4643 [inline]
>>>>>   kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>   comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>>>>   comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>>>>   do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>>>>   comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>   vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>   __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>   __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>   __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>
>>>> I took a quick look at this, and surely looks like a comedi bug. If you
>>>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
>>>> a detach and frees the device, regardless of whether anyone has it
>>>> opened or not?! It's got some odd notion of checking whether it's busy
>>>> or not. For this case, someone has a poll active on the device, yet it
>>>> still happily frees it.
>>>>
>>>> CC'ing some folks, as this looks utterly broken.
>>>
>>> Case in point, I added:
>>>
>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>> index 376130bfba8a..4d5fde012558 100644
>>> --- a/drivers/comedi/drivers.c
>>> +++ b/drivers/comedi/drivers.c
>>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>>>   				kfree(s->private);
>>>   			comedi_free_subdevice_minor(s);
>>>   			if (s->async) {
>>> +				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>   				comedi_buf_alloc(dev, s, 0);
>>>   				kfree(s->async);
>>>   			}
>>>
>>> and this is the first thing that triggers:
>>>
>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
>>> Modules linked in:
>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE
>>> Hardware name: linux,dummy-virt (DT)
>>> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>>> pc : comedi_device_detach+0x510/0x720
>>> lr : comedi_device_detach+0x1dc/0x720
>>> sp : ffff80008aeb7880
>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>> Call trace:
>>>   comedi_device_detach+0x510/0x720 (P)
>>>   do_devconfig_ioctl+0x37c/0x4b8
>>>   comedi_unlocked_ioctl+0x33c/0x2bd8
>>>   __arm64_sys_ioctl+0x124/0x1a0
>>>   invoke_syscall.constprop.0+0x60/0x2a0
>>>   el0_svc_common.constprop.0+0x148/0x240
>>>   do_el0_svc+0x40/0x60
>>>   el0_svc+0x44/0xe0
>>>   el0t_64_sync_handler+0x104/0x130
>>>   el0t_64_sync+0x170/0x178
>>>
>>> Not sure what the right fix for comedi is here, it'd probably be at
>>> least somewhat saner if it only allowed removal of the device when the
>>> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
>>> and allowing blanket removal seems highly suspicious / broken.
>>>
>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>
>>> #syz set subsystems: kernel
>>
>> Something like the below may help, at least it'll tell us the device is
>> busy if there's a poll active on it.
>>
>> #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
>>
>>
>> diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
>> index 3383a7ce27ff..ea96bc4b818e 100644
>> --- a/drivers/comedi/comedi_fops.c
>> +++ b/drivers/comedi/comedi_fops.c
>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
>>   static int is_device_busy(struct comedi_device *dev)
>>   {
>>   	struct comedi_subdevice *s;
>> -	int i;
>> +	int i, is_busy = 0;
>>   
>>   	lockdep_assert_held(&dev->mutex);
>>   	if (!dev->attached)
>>   		return 0;
>>   
>> +	/* prevent new polls */
>> +	down_write(&dev->attach_lock);
>> +
>>   	for (i = 0; i < dev->n_subdevices; i++) {
>>   		s = &dev->subdevices[i];
>> -		if (s->busy)
>> -			return 1;
>> -		if (s->async && comedi_buf_is_mmapped(s))
>> -			return 1;
>> +		if (s->busy) {
>> +			is_busy = 1;
>> +			break;
>> +		}
>> +		if (!s->async)
>> +			continue;
>> +		if (comedi_buf_is_mmapped(s) ||
>> +		    waitqueue_active(&s->async->wait_head)) {
>> +			is_busy = 1;
>> +			break;
>> +		}
>>   	}
>> -
>> -	return 0;
>> +	up_write(&dev->attach_lock);
>> +	return is_busy;
>>   }
>>   
>>   /*
> 
> Haven't heard anything back, so I guess I'll send it out as a patch?
> 

Not yet, please. I'm working on it to close the remaining part of the 
race condition window.

-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:21       ` [syzbot] [io-uring?] " Jens Axboe
  2025-07-22 12:30         ` Ian Abbott
@ 2025-07-22 12:31         ` Greg Kroah-Hartman
  2025-07-22 12:44           ` Jens Axboe
  1 sibling, 1 reply; 26+ messages in thread
From: Greg Kroah-Hartman @ 2025-07-22 12:31 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten

On Tue, Jul 22, 2025 at 06:21:50AM -0600, Jens Axboe wrote:
> On 7/20/25 1:00 PM, Jens Axboe wrote:
> > On 7/20/25 12:49 PM, Jens Axboe wrote:
> >> On 7/20/25 12:24 PM, Jens Axboe wrote:
> >>> On 7/19/25 11:29 AM, syzbot wrote:
> >>>> Hello,
> >>>>
> >>>> syzbot found the following issue on:
> >>>>
> >>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
> >>>> git tree:       upstream
> >>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
> >>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> >>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> >>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> >>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
> >>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
> >>>>
> >>>> Downloadable assets:
> >>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
> >>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
> >>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
> >>>>
> >>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> >>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
> >>>>
> >>>> ==================================================================
> >>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> >>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> >>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
> >>>>
> >>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
> >>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
> >>>> Workqueue: events io_fallback_req_func
> >>>> Call Trace:
> >>>>  <TASK>
> >>>>  __dump_stack lib/dump_stack.c:94 [inline]
> >>>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
> >>>>  print_address_description mm/kasan/report.c:378 [inline]
> >>>>  print_report+0xcd/0x610 mm/kasan/report.c:480
> >>>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
> >>>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
> >>>>  kasan_check_byte include/linux/kasan.h:399 [inline]
> >>>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
> >>>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
> >>>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> >>>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> >>>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
> >>>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
> >>>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
> >>>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
> >>>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
> >>>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
> >>>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
> >>>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
> >>>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
> >>>>  kthread+0x3c5/0x780 kernel/kthread.c:464
> >>>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
> >>>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >>>>  </TASK>
> >>>>
> >>>> Allocated by task 6154:
> >>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> >>>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
> >>>>  kmalloc_noprof include/linux/slab.h:905 [inline]
> >>>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
> >>>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
> >>>>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
> >>>>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
> >>>>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
> >>>>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
> >>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
> >>>>  vfs_ioctl fs/ioctl.c:51 [inline]
> >>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
> >>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
> >>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >>>>
> >>>> Freed by task 6156:
> >>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
> >>>>  poison_slab_object mm/kasan/common.c:247 [inline]
> >>>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
> >>>>  kasan_slab_free include/linux/kasan.h:233 [inline]
> >>>>  slab_free_hook mm/slub.c:2381 [inline]
> >>>>  slab_free mm/slub.c:4643 [inline]
> >>>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
> >>>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
> >>>>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
> >>>>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
> >>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
> >>>>  vfs_ioctl fs/ioctl.c:51 [inline]
> >>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
> >>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
> >>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >>>
> >>> I took a quick look at this, and surely looks like a comedi bug. If you
> >>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
> >>> a detach and frees the device, regardless of whether anyone has it
> >>> opened or not?! It's got some odd notion of checking whether it's busy
> >>> or not. For this case, someone has a poll active on the device, yet it
> >>> still happily frees it.
> >>>
> >>> CC'ing some folks, as this looks utterly broken.
> >>
> >> Case in point, I added:
> >>
> >> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
> >> index 376130bfba8a..4d5fde012558 100644
> >> --- a/drivers/comedi/drivers.c
> >> +++ b/drivers/comedi/drivers.c
> >> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
> >>  				kfree(s->private);
> >>  			comedi_free_subdevice_minor(s);
> >>  			if (s->async) {
> >> +				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
> >>  				comedi_buf_alloc(dev, s, 0);
> >>  				kfree(s->async);
> >>  			}
> >>
> >> and this is the first thing that triggers:
> >>
> >> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
> >> Modules linked in:
> >> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE 
> >> Hardware name: linux,dummy-virt (DT)
> >> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
> >> pc : comedi_device_detach+0x510/0x720
> >> lr : comedi_device_detach+0x1dc/0x720
> >> sp : ffff80008aeb7880
> >> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
> >> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
> >> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
> >> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
> >> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
> >> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
> >> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
> >> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
> >> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
> >> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
> >> Call trace:
> >>  comedi_device_detach+0x510/0x720 (P)
> >>  do_devconfig_ioctl+0x37c/0x4b8
> >>  comedi_unlocked_ioctl+0x33c/0x2bd8
> >>  __arm64_sys_ioctl+0x124/0x1a0
> >>  invoke_syscall.constprop.0+0x60/0x2a0
> >>  el0_svc_common.constprop.0+0x148/0x240
> >>  do_el0_svc+0x40/0x60
> >>  el0_svc+0x44/0xe0
> >>  el0t_64_sync_handler+0x104/0x130
> >>  el0t_64_sync+0x170/0x178
> >>
> >> Not sure what the right fix for comedi is here, it'd probably be at
> >> least somewhat saner if it only allowed removal of the device when the
> >> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
> >> and allowing blanket removal seems highly suspicious / broken.
> >>
> >> As there's no comedi subsystem in syzbot, moving it to kernel:
> >>
> >> #syz set subsystems: kernel
> > 
> > Something like the below may help, at least it'll tell us the device is
> > busy if there's a poll active on it.
> > 
> > #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
> > 
> > 
> > diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
> > index 3383a7ce27ff..ea96bc4b818e 100644
> > --- a/drivers/comedi/comedi_fops.c
> > +++ b/drivers/comedi/comedi_fops.c
> > @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
> >  static int is_device_busy(struct comedi_device *dev)
> >  {
> >  	struct comedi_subdevice *s;
> > -	int i;
> > +	int i, is_busy = 0;
> >  
> >  	lockdep_assert_held(&dev->mutex);
> >  	if (!dev->attached)
> >  		return 0;
> >  
> > +	/* prevent new polls */
> > +	down_write(&dev->attach_lock);
> > +
> >  	for (i = 0; i < dev->n_subdevices; i++) {
> >  		s = &dev->subdevices[i];
> > -		if (s->busy)
> > -			return 1;
> > -		if (s->async && comedi_buf_is_mmapped(s))
> > -			return 1;
> > +		if (s->busy) {
> > +			is_busy = 1;
> > +			break;
> > +		}
> > +		if (!s->async)
> > +			continue;
> > +		if (comedi_buf_is_mmapped(s) ||
> > +		    waitqueue_active(&s->async->wait_head)) {
> > +			is_busy = 1;
> > +			break;
> > +		}
> >  	}
> > -
> > -	return 0;
> > +	up_write(&dev->attach_lock);
> > +	return is_busy;
> >  }
> >  
> >  /*
> 
> Haven't heard anything back, so I guess I'll send it out as a patch?

Please do.  Note, a bunch of comedi bugfixes for syzbot-found-issues
just langed in 6.16-rc7.  I don't know if there's a way to trigger
syzbot to re-run its check on that branch before you submit this?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:30         ` Ian Abbott
@ 2025-07-22 12:43           ` Jens Axboe
  0 siblings, 0 replies; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 12:43 UTC (permalink / raw)
  To: Ian Abbott, syzbot, io-uring, linux-kernel, syzkaller-bugs,
	hsweeten, Greg Kroah-Hartman

On 7/22/25 6:30 AM, Ian Abbott wrote:
> On 22/07/2025 13:21, Jens Axboe wrote:
>> On 7/20/25 1:00 PM, Jens Axboe wrote:
>>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>>>> Hello,
>>>>>>
>>>>>> syzbot found the following issue on:
>>>>>>
>>>>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>>>>>> git tree:       upstream
>>>>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>>>>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>>>>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>>>>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>>
>>>>>> Downloadable assets:
>>>>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>>
>>>>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>>>>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>>
>>>>>> ==================================================================
>>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>>
>>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>>>>>> Workqueue: events io_fallback_req_func
>>>>>> Call Trace:
>>>>>>   <TASK>
>>>>>>   __dump_stack lib/dump_stack.c:94 [inline]
>>>>>>   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>>   print_address_description mm/kasan/report.c:378 [inline]
>>>>>>   print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>>   kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>>   __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>>   kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>>   lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>>   lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>>   __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>>   _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>>   spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>>>   io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>>>   io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>>   io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>>   io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>>   io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>>   process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>>   process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>>   worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>>   kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>>   ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>>   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>>   </TASK>
>>>>>>
>>>>>> Allocated by task 6154:
>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>   poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>>   __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>>   kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>>   kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>>   __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>>>>>   __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>>>>>   comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>>>>>   comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>>>>>   do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>>>>>   comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>>   vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>>   __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>>   __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>>   __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>
>>>>>> Freed by task 6156:
>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>   kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>>   poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>>   __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>>   kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>>   slab_free_hook mm/slub.c:2381 [inline]
>>>>>>   slab_free mm/slub.c:4643 [inline]
>>>>>>   kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>>   comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>>>>>   comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>>>>>   do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>>>>>   comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>>   vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>>   __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>>   __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>>   __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> I took a quick look at this, and surely looks like a comedi bug. If you
>>>>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
>>>>> a detach and frees the device, regardless of whether anyone has it
>>>>> opened or not?! It's got some odd notion of checking whether it's busy
>>>>> or not. For this case, someone has a poll active on the device, yet it
>>>>> still happily frees it.
>>>>>
>>>>> CC'ing some folks, as this looks utterly broken.
>>>>
>>>> Case in point, I added:
>>>>
>>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>>> index 376130bfba8a..4d5fde012558 100644
>>>> --- a/drivers/comedi/drivers.c
>>>> +++ b/drivers/comedi/drivers.c
>>>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>>>>                   kfree(s->private);
>>>>               comedi_free_subdevice_minor(s);
>>>>               if (s->async) {
>>>> +                WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>>                   comedi_buf_alloc(dev, s, 0);
>>>>                   kfree(s->async);
>>>>               }
>>>>
>>>> and this is the first thing that triggers:
>>>>
>>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
>>>> Modules linked in:
>>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE
>>>> Hardware name: linux,dummy-virt (DT)
>>>> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>>>> pc : comedi_device_detach+0x510/0x720
>>>> lr : comedi_device_detach+0x1dc/0x720
>>>> sp : ffff80008aeb7880
>>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>>> Call trace:
>>>>   comedi_device_detach+0x510/0x720 (P)
>>>>   do_devconfig_ioctl+0x37c/0x4b8
>>>>   comedi_unlocked_ioctl+0x33c/0x2bd8
>>>>   __arm64_sys_ioctl+0x124/0x1a0
>>>>   invoke_syscall.constprop.0+0x60/0x2a0
>>>>   el0_svc_common.constprop.0+0x148/0x240
>>>>   do_el0_svc+0x40/0x60
>>>>   el0_svc+0x44/0xe0
>>>>   el0t_64_sync_handler+0x104/0x130
>>>>   el0t_64_sync+0x170/0x178
>>>>
>>>> Not sure what the right fix for comedi is here, it'd probably be at
>>>> least somewhat saner if it only allowed removal of the device when the
>>>> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
>>>> and allowing blanket removal seems highly suspicious / broken.
>>>>
>>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>>
>>>> #syz set subsystems: kernel
>>>
>>> Something like the below may help, at least it'll tell us the device is
>>> busy if there's a poll active on it.
>>>
>>> #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
>>>
>>>
>>> diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
>>> index 3383a7ce27ff..ea96bc4b818e 100644
>>> --- a/drivers/comedi/comedi_fops.c
>>> +++ b/drivers/comedi/comedi_fops.c
>>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
>>>   static int is_device_busy(struct comedi_device *dev)
>>>   {
>>>       struct comedi_subdevice *s;
>>> -    int i;
>>> +    int i, is_busy = 0;
>>>         lockdep_assert_held(&dev->mutex);
>>>       if (!dev->attached)
>>>           return 0;
>>>   +    /* prevent new polls */
>>> +    down_write(&dev->attach_lock);
>>> +
>>>       for (i = 0; i < dev->n_subdevices; i++) {
>>>           s = &dev->subdevices[i];
>>> -        if (s->busy)
>>> -            return 1;
>>> -        if (s->async && comedi_buf_is_mmapped(s))
>>> -            return 1;
>>> +        if (s->busy) {
>>> +            is_busy = 1;
>>> +            break;
>>> +        }
>>> +        if (!s->async)
>>> +            continue;
>>> +        if (comedi_buf_is_mmapped(s) ||
>>> +            waitqueue_active(&s->async->wait_head)) {
>>> +            is_busy = 1;
>>> +            break;
>>> +        }
>>>       }
>>> -
>>> -    return 0;
>>> +    up_write(&dev->attach_lock);
>>> +    return is_busy;
>>>   }
>>>     /*
>>
>> Haven't heard anything back, so I guess I'll send it out as a patch?
>>
> 
> Not yet, please. I'm working on it to close the remaining part of the race condition window.

I updated mine, see below. Will fling it at syzbot shortly.

diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index c83fd14dd7ad..58b034e45283 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -782,24 +782,33 @@ void comedi_device_cancel_all(struct comedi_device *dev)
 	}
 }
 
-static int is_device_busy(struct comedi_device *dev)
+static int start_detach(struct comedi_device *dev)
 {
 	struct comedi_subdevice *s;
-	int i;
+	int i, is_busy = 0;
 
 	lockdep_assert_held(&dev->mutex);
+	lockdep_assert_held(&dev->attach_lock);
 	if (!dev->attached)
 		return 0;
 
 	for (i = 0; i < dev->n_subdevices; i++) {
 		s = &dev->subdevices[i];
-		if (s->busy)
-			return 1;
-		if (s->async && comedi_buf_is_mmapped(s))
-			return 1;
+		if (s->busy) {
+			is_busy = 1;
+			break;
+		}
+		if (!s->async)
+			continue;
+		if (comedi_buf_is_mmapped(s) ||
+		    wq_has_sleeper(&s->async->wait_head)) {
+			is_busy = 1;
+			break;
+		}
 	}
-
-	return 0;
+	if (!is_busy)
+		dev->detaching = 1;
+	return is_busy;
 }
 
 /*
@@ -825,8 +834,13 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
 		return -EPERM;
 
 	if (!arg) {
-		if (is_device_busy(dev))
+		/* prevent new polls */
+		down_write(&dev->attach_lock);
+		if (start_detach(dev)) {
+			up_write(&dev->attach_lock);
 			return -EBUSY;
+		}
+		up_write(&dev->attach_lock);
 		if (dev->attached) {
 			struct module *driver_module = dev->driver->module;
 
@@ -2479,7 +2493,7 @@ static __poll_t comedi_poll(struct file *file, poll_table *wait)
 
 	down_read(&dev->attach_lock);
 
-	if (!dev->attached) {
+	if (!dev->attached || dev->detaching) {
 		dev_dbg(dev->class_dev, "no driver attached\n");
 		goto done;
 	}
diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedidev.h
index 4cb0400ad616..b2bec668785f 100644
--- a/include/linux/comedi/comedidev.h
+++ b/include/linux/comedi/comedidev.h
@@ -545,6 +545,7 @@ struct comedi_device {
 	const char *board_name;
 	const void *board_ptr;
 	unsigned int attached:1;
+	unsigned int detaching:1;
 	unsigned int ioenabled:1;
 	spinlock_t spinlock;	/* generic spin-lock for low-level driver */
 	struct mutex mutex;	/* generic mutex for COMEDI core */


-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:31         ` Greg Kroah-Hartman
@ 2025-07-22 12:44           ` Jens Axboe
  0 siblings, 0 replies; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 12:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, abbotti, hsweeten

On 7/22/25 6:31 AM, Greg Kroah-Hartman wrote:
> On Tue, Jul 22, 2025 at 06:21:50AM -0600, Jens Axboe wrote:
>> On 7/20/25 1:00 PM, Jens Axboe wrote:
>>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>>>> Hello,
>>>>>>
>>>>>> syzbot found the following issue on:
>>>>>>
>>>>>> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
>>>>>> git tree:       upstream
>>>>>> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
>>>>>> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>>> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
>>>>>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
>>>>>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>>
>>>>>> Downloadable assets:
>>>>>> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>>> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>>> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>>
>>>>>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>>>>>> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>>
>>>>>> ==================================================================
>>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>>
>>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full) 
>>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
>>>>>> Workqueue: events io_fallback_req_func
>>>>>> Call Trace:
>>>>>>  <TASK>
>>>>>>  __dump_stack lib/dump_stack.c:94 [inline]
>>>>>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>>  print_address_description mm/kasan/report.c:378 [inline]
>>>>>>  print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>>  kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>>  kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>>  </TASK>
>>>>>>
>>>>>> Allocated by task 6154:
>>>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>>  kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
>>>>>>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
>>>>>>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
>>>>>>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
>>>>>>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
>>>>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>
>>>>>> Freed by task 6156:
>>>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>>  poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>>  kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>>  slab_free_hook mm/slub.c:2381 [inline]
>>>>>>  slab_free mm/slub.c:4643 [inline]
>>>>>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
>>>>>>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
>>>>>>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
>>>>>>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
>>>>>>  vfs_ioctl fs/ioctl.c:51 [inline]
>>>>>>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>>>>>>  __se_sys_ioctl fs/ioctl.c:893 [inline]
>>>>>>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> I took a quick look at this, and surely looks like a comedi bug. If you
>>>>> call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
>>>>> a detach and frees the device, regardless of whether anyone has it
>>>>> opened or not?! It's got some odd notion of checking whether it's busy
>>>>> or not. For this case, someone has a poll active on the device, yet it
>>>>> still happily frees it.
>>>>>
>>>>> CC'ing some folks, as this looks utterly broken.
>>>>
>>>> Case in point, I added:
>>>>
>>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>>> index 376130bfba8a..4d5fde012558 100644
>>>> --- a/drivers/comedi/drivers.c
>>>> +++ b/drivers/comedi/drivers.c
>>>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>>>>  				kfree(s->private);
>>>>  			comedi_free_subdevice_minor(s);
>>>>  			if (s->async) {
>>>> +				WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>>  				comedi_buf_alloc(dev, s, 0);
>>>>  				kfree(s->async);
>>>>  			}
>>>>
>>>> and this is the first thing that triggers:
>>>>
>>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
>>>> Modules linked in:
>>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE 
>>>> Hardware name: linux,dummy-virt (DT)
>>>> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>>>> pc : comedi_device_detach+0x510/0x720
>>>> lr : comedi_device_detach+0x1dc/0x720
>>>> sp : ffff80008aeb7880
>>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>>> Call trace:
>>>>  comedi_device_detach+0x510/0x720 (P)
>>>>  do_devconfig_ioctl+0x37c/0x4b8
>>>>  comedi_unlocked_ioctl+0x33c/0x2bd8
>>>>  __arm64_sys_ioctl+0x124/0x1a0
>>>>  invoke_syscall.constprop.0+0x60/0x2a0
>>>>  el0_svc_common.constprop.0+0x148/0x240
>>>>  do_el0_svc+0x40/0x60
>>>>  el0_svc+0x44/0xe0
>>>>  el0t_64_sync_handler+0x104/0x130
>>>>  el0t_64_sync+0x170/0x178
>>>>
>>>> Not sure what the right fix for comedi is here, it'd probably be at
>>>> least somewhat saner if it only allowed removal of the device when the
>>>> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
>>>> and allowing blanket removal seems highly suspicious / broken.
>>>>
>>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>>
>>>> #syz set subsystems: kernel
>>>
>>> Something like the below may help, at least it'll tell us the device is
>>> busy if there's a poll active on it.
>>>
>>> #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
>>>
>>>
>>> diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
>>> index 3383a7ce27ff..ea96bc4b818e 100644
>>> --- a/drivers/comedi/comedi_fops.c
>>> +++ b/drivers/comedi/comedi_fops.c
>>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct comedi_device *dev)
>>>  static int is_device_busy(struct comedi_device *dev)
>>>  {
>>>  	struct comedi_subdevice *s;
>>> -	int i;
>>> +	int i, is_busy = 0;
>>>  
>>>  	lockdep_assert_held(&dev->mutex);
>>>  	if (!dev->attached)
>>>  		return 0;
>>>  
>>> +	/* prevent new polls */
>>> +	down_write(&dev->attach_lock);
>>> +
>>>  	for (i = 0; i < dev->n_subdevices; i++) {
>>>  		s = &dev->subdevices[i];
>>> -		if (s->busy)
>>> -			return 1;
>>> -		if (s->async && comedi_buf_is_mmapped(s))
>>> -			return 1;
>>> +		if (s->busy) {
>>> +			is_busy = 1;
>>> +			break;
>>> +		}
>>> +		if (!s->async)
>>> +			continue;
>>> +		if (comedi_buf_is_mmapped(s) ||
>>> +		    waitqueue_active(&s->async->wait_head)) {
>>> +			is_busy = 1;
>>> +			break;
>>> +		}
>>>  	}
>>> -
>>> -	return 0;
>>> +	up_write(&dev->attach_lock);
>>> +	return is_busy;
>>>  }
>>>  
>>>  /*
>>
>> Haven't heard anything back, so I guess I'll send it out as a patch?
> 
> Please do.  Note, a bunch of comedi bugfixes for syzbot-found-issues
> just langed in 6.16-rc7.  I don't know if there's a way to trigger
> syzbot to re-run its check on that branch before you submit this?

I updated the above a bit, will send out an email shortly for syzbot to
re-test. If that's fine, then I'll send it out officially.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 19:00     ` Jens Axboe
  2025-07-20 19:19       ` [syzbot] [kernel] " syzbot
  2025-07-22 12:21       ` [syzbot] [io-uring?] " Jens Axboe
@ 2025-07-22 12:47       ` Ian Abbott
  2025-07-22 13:00         ` Jens Axboe
  2025-07-22 13:53         ` Jens Axboe
  2 siblings, 2 replies; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 12:47 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On Sun, 20 Jul 2025 13:00:59 -0600
Jens Axboe <axboe@kernel.dk> wrote:

> On 7/20/25 12:49 PM, Jens Axboe wrote:
> > On 7/20/25 12:24 PM, Jens Axboe wrote:  
> >> On 7/19/25 11:29 AM, syzbot wrote:  
> >>> Hello,
> >>>
> >>> syzbot found the following issue on:
> >>>
> >>> HEAD commit:    4871b7cb27f4 Merge tag
> >>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
> >>> console output:
> >>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
> >>> config:
> >>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> >>> dashboard link:
> >>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> >>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
> >>> Binutils for Debian) 2.40 syz repro:
> >>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
> >>> reproducer:
> >>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
> >>>
> >>> Downloadable assets:
> >>> disk image (non-bootable):
> >>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
> >>> vmlinux:
> >>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
> >>> kernel image:
> >>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
> >>>
> >>> IMPORTANT: if you fix the issue, please add the following tag to
> >>> the commit: Reported-by:
> >>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
> >>>
> >>> ==================================================================
> >>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
> >>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
> >>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
> >>> kernel/locking/spinlock.c:170 Read of size 1 at addr
> >>> ffff88803c6f42b0 by task kworker/2:2/1339
> >>>
> >>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
> >>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
> >>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
> >>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
> >>> io_fallback_req_func Call Trace: <TASK>
> >>>  __dump_stack lib/dump_stack.c:94 [inline]
> >>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
> >>>  print_address_description mm/kasan/report.c:378 [inline]
> >>>  print_report+0xcd/0x610 mm/kasan/report.c:480
> >>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
> >>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
> >>>  kasan_check_byte include/linux/kasan.h:399 [inline]
> >>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
> >>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
> >>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> >>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> >>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
> >>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
> >>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
> >>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
> >>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
> >>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
> >>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
> >>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
> >>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
> >>>  kthread+0x3c5/0x780 kernel/kthread.c:464
> >>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
> >>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >>>  </TASK>
> >>>
> >>> Allocated by task 6154:
> >>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> >>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
> >>>  kmalloc_noprof include/linux/slab.h:905 [inline]
> >>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
> >>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664
> >>> [inline] __comedi_device_postconfig drivers/comedi/drivers.c:721
> >>> [inline] comedi_device_postconfig+0x2cb/0xc80
> >>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
> >>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
> >>> drivers/comedi/comedi_fops.c:855
> >>> comedi_unlocked_ioctl+0x15bb/0x2e90
> >>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
> >>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
> >>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >>>
> >>> Freed by task 6156:
> >>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
> >>>  poison_slab_object mm/kasan/common.c:247 [inline]
> >>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
> >>>  kasan_slab_free include/linux/kasan.h:233 [inline]
> >>>  slab_free_hook mm/slub.c:2381 [inline]
> >>>  slab_free mm/slub.c:4643 [inline]
> >>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
> >>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171
> >>> [inline] comedi_device_detach+0x2a4/0x9e0
> >>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
> >>> drivers/comedi/comedi_fops.c:833
> >>> comedi_unlocked_ioctl+0x15bb/0x2e90
> >>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
> >>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
> >>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f  
> >>
> >> I took a quick look at this, and surely looks like a comedi bug.
> >> If you call the ioctl part (do_devconfig_ioctl()) with a NULL arg,
> >> it just does a detach and frees the device, regardless of whether
> >> anyone has it opened or not?! It's got some odd notion of checking
> >> whether it's busy or not. For this case, someone has a poll active
> >> on the device, yet it still happily frees it.
> >>
> >> CC'ing some folks, as this looks utterly broken.  
> > 
> > Case in point, I added:
> > 
> > diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
> > index 376130bfba8a..4d5fde012558 100644
> > --- a/drivers/comedi/drivers.c
> > +++ b/drivers/comedi/drivers.c
> > @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct
> > comedi_device *dev) kfree(s->private);
> >  			comedi_free_subdevice_minor(s);
> >  			if (s->async) {
> > +
> > WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
> > comedi_buf_alloc(dev, s, 0); kfree(s->async);
> >  			}
> > 
> > and this is the first thing that triggers:
> > 
> > WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
> > comedi_device_detach+0x510/0x720 Modules linked in:
> > CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
> > 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
> > linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
> > +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
> > lr : comedi_device_detach+0x1dc/0x720
> > sp : ffff80008aeb7880
> > x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
> > x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
> > x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
> > x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
> > x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
> > x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
> > x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
> > x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
> > x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
> > x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
> > Call trace:
> >  comedi_device_detach+0x510/0x720 (P)
> >  do_devconfig_ioctl+0x37c/0x4b8
> >  comedi_unlocked_ioctl+0x33c/0x2bd8
> >  __arm64_sys_ioctl+0x124/0x1a0
> >  invoke_syscall.constprop.0+0x60/0x2a0
> >  el0_svc_common.constprop.0+0x148/0x240
> >  do_el0_svc+0x40/0x60
> >  el0_svc+0x44/0xe0
> >  el0t_64_sync_handler+0x104/0x130
> >  el0t_64_sync+0x170/0x178
> > 
> > Not sure what the right fix for comedi is here, it'd probably be at
> > least somewhat saner if it only allowed removal of the device when
> > the ref count would be 1 (for the ioctl itself). Just ignoring the
> > file ref and allowing blanket removal seems highly suspicious /
> > broken.
> > 
> > As there's no comedi subsystem in syzbot, moving it to kernel:
> > 
> > #syz set subsystems: kernel  
> 
> Something like the below may help, at least it'll tell us the device
> is busy if there's a poll active on it.
> 
> #syz test:
> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> master
> 
> 
> diff --git a/drivers/comedi/comedi_fops.c
> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e 100644
> --- a/drivers/comedi/comedi_fops.c
> +++ b/drivers/comedi/comedi_fops.c
> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
> comedi_device *dev) static int is_device_busy(struct comedi_device
> *dev) {
>  	struct comedi_subdevice *s;
> -	int i;
> +	int i, is_busy = 0;
>  
>  	lockdep_assert_held(&dev->mutex);
>  	if (!dev->attached)
>  		return 0;
>  
> +	/* prevent new polls */
> +	down_write(&dev->attach_lock);
> +
>  	for (i = 0; i < dev->n_subdevices; i++) {
>  		s = &dev->subdevices[i];
> -		if (s->busy)
> -			return 1;
> -		if (s->async && comedi_buf_is_mmapped(s))
> -			return 1;
> +		if (s->busy) {
> +			is_busy = 1;
> +			break;
> +		}
> +		if (!s->async)
> +			continue;
> +		if (comedi_buf_is_mmapped(s) ||
> +		    waitqueue_active(&s->async->wait_head)) {
> +			is_busy = 1;
> +			break;
> +		}
>  	}
> -
> -	return 0;
> +	up_write(&dev->attach_lock);
> +	return is_busy;
>  }
>  
>  /*
> 

Thanks for your investigation and initial fix. I think dev->attach_lock
needs to be write-locked before calling is_device_busy() and released
after comedi_device_detach() (although that also write-locks it, so we
need to refactor that). Otherwise, someone could get added to the
wait_head after is_device_busy() returns.

Something like this:

diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 3383a7ce27ff..a0048510fc40 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -787,6 +787,7 @@ static int is_device_busy(struct comedi_device *dev)
 	struct comedi_subdevice *s;
 	int i;
 
+	lockdep_assert_held_write(&dev->attach_lock);
 	lockdep_assert_held(&dev->mutex);
 	if (!dev->attached)
 		return 0;
@@ -795,7 +796,12 @@ static int is_device_busy(struct comedi_device *dev)
 		s = &dev->subdevices[i];
 		if (s->busy)
 			return 1;
-		if (s->async && comedi_buf_is_mmapped(s))
+		if (!s->async)
+			continue;
+		if (comedi_buf_is_mmapped(s))
+			return 1;
+		/* There may be transient active polls. */
+		if (waitqueue_active(&s->async->wait_head))
 			return 1;
 	}
 
@@ -825,15 +831,22 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
 		return -EPERM;
 
 	if (!arg) {
-		if (is_device_busy(dev))
-			return -EBUSY;
+		int rc = 0;
+
 		if (dev->attached) {
-			struct module *driver_module = dev->driver->module;
+			down_write(&dev->attach_lock);
+			if (is_device_busy(dev)) {
+				rc = -EBUSY;
+			} else {
+				struct module *driver_module =
+					dev->driver->module;
 
-			comedi_device_detach(dev);
-			module_put(driver_module);
+				comedi_device_detach_locked(dev);
+				module_put(driver_module);
+			}
+			up_write(&dev->attach_lock);
 		}
-		return 0;
+		return rc;
 	}
 
 	if (copy_from_user(&it, arg, sizeof(it)))
diff --git a/drivers/comedi/comedi_internal.h b/drivers/comedi/comedi_internal.h
index 9b3631a654c8..cf10ba016ebc 100644
--- a/drivers/comedi/comedi_internal.h
+++ b/drivers/comedi/comedi_internal.h
@@ -50,6 +50,7 @@ extern struct mutex comedi_drivers_list_lock;
 int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
 	       struct comedi_insn *insn, unsigned int *data);
 
+void comedi_device_detach_locked(struct comedi_device *dev);
 void comedi_device_detach(struct comedi_device *dev);
 int comedi_device_attach(struct comedi_device *dev,
 			 struct comedi_devconfig *it);
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index 376130bfba8a..f5c2ee271d0e 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -158,7 +158,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
 	int i;
 	struct comedi_subdevice *s;
 
-	lockdep_assert_held(&dev->attach_lock);
+	lockdep_assert_held_write(&dev->attach_lock);
 	lockdep_assert_held(&dev->mutex);
 	if (dev->subdevices) {
 		for (i = 0; i < dev->n_subdevices; i++) {
@@ -196,16 +196,23 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
 	comedi_clear_hw_dev(dev);
 }
 
-void comedi_device_detach(struct comedi_device *dev)
+void comedi_device_detach_locked(struct comedi_device *dev)
 {
+	lockdep_assert_held_write(&dev->attach_lock);
 	lockdep_assert_held(&dev->mutex);
 	comedi_device_cancel_all(dev);
-	down_write(&dev->attach_lock);
 	dev->attached = false;
 	dev->detach_count++;
 	if (dev->driver)
 		dev->driver->detach(dev);
 	comedi_device_detach_cleanup(dev);
+}
+
+void comedi_device_detach(struct comedi_device *dev)
+{
+	lockdep_assert_held(&dev->mutex);
+	down_write(&dev->attach_lock);
+	comedi_device_detach_locked(dev);
 	up_write(&dev->attach_lock);
 }

-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
                   ` (3 preceding siblings ...)
  2025-07-20 18:44 ` Forwarded: " syzbot
@ 2025-07-22 12:47 ` Jens Axboe
  2025-07-22 13:14   ` [syzbot] [kernel] " syzbot
  4 siblings, 1 reply; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 12:47 UTC (permalink / raw)
  To: syzbot, io-uring, linux-kernel, syzkaller-bugs

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index c83fd14dd7ad..58b034e45283 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -782,24 +782,33 @@ void comedi_device_cancel_all(struct comedi_device *dev)
 	}
 }
 
-static int is_device_busy(struct comedi_device *dev)
+static int start_detach(struct comedi_device *dev)
 {
 	struct comedi_subdevice *s;
-	int i;
+	int i, is_busy = 0;
 
 	lockdep_assert_held(&dev->mutex);
+	lockdep_assert_held(&dev->attach_lock);
 	if (!dev->attached)
 		return 0;
 
 	for (i = 0; i < dev->n_subdevices; i++) {
 		s = &dev->subdevices[i];
-		if (s->busy)
-			return 1;
-		if (s->async && comedi_buf_is_mmapped(s))
-			return 1;
+		if (s->busy) {
+			is_busy = 1;
+			break;
+		}
+		if (!s->async)
+			continue;
+		if (comedi_buf_is_mmapped(s) ||
+		    wq_has_sleeper(&s->async->wait_head)) {
+			is_busy = 1;
+			break;
+		}
 	}
-
-	return 0;
+	if (!is_busy)
+		dev->detaching = 1;
+	return is_busy;
 }
 
 /*
@@ -825,8 +834,13 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
 		return -EPERM;
 
 	if (!arg) {
-		if (is_device_busy(dev))
+		/* prevent new polls */
+		down_write(&dev->attach_lock);
+		if (start_detach(dev)) {
+			up_write(&dev->attach_lock);
 			return -EBUSY;
+		}
+		up_write(&dev->attach_lock);
 		if (dev->attached) {
 			struct module *driver_module = dev->driver->module;
 
@@ -2479,7 +2493,7 @@ static __poll_t comedi_poll(struct file *file, poll_table *wait)
 
 	down_read(&dev->attach_lock);
 
-	if (!dev->attached) {
+	if (!dev->attached || dev->detaching) {
 		dev_dbg(dev->class_dev, "no driver attached\n");
 		goto done;
 	}
diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedidev.h
index 4cb0400ad616..b2bec668785f 100644
--- a/include/linux/comedi/comedidev.h
+++ b/include/linux/comedi/comedidev.h
@@ -545,6 +545,7 @@ struct comedi_device {
 	const char *board_name;
 	const void *board_ptr;
 	unsigned int attached:1;
+	unsigned int detaching:1;
 	unsigned int ioenabled:1;
 	spinlock_t spinlock;	/* generic spin-lock for low-level driver */
 	struct mutex mutex;	/* generic mutex for COMEDI core */

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:47       ` Ian Abbott
@ 2025-07-22 13:00         ` Jens Axboe
  2025-07-22 13:07           ` Ian Abbott
  2025-07-22 13:53         ` Jens Axboe
  1 sibling, 1 reply; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 13:00 UTC (permalink / raw)
  To: Ian Abbott
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On 7/22/25 6:47 AM, Ian Abbott wrote:
> On Sun, 20 Jul 2025 13:00:59 -0600
> Jens Axboe <axboe@kernel.dk> wrote:
> 
>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>> On 7/20/25 12:24 PM, Jens Axboe wrote:  
>>>> On 7/19/25 11:29 AM, syzbot wrote:  
>>>>> Hello,
>>>>>
>>>>> syzbot found the following issue on:
>>>>>
>>>>> HEAD commit:    4871b7cb27f4 Merge tag
>>>>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
>>>>> console output:
>>>>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
>>>>> config:
>>>>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>> dashboard link:
>>>>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
>>>>> Binutils for Debian) 2.40 syz repro:
>>>>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
>>>>> reproducer:
>>>>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>
>>>>> Downloadable assets:
>>>>> disk image (non-bootable):
>>>>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>> vmlinux:
>>>>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>> kernel image:
>>>>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>
>>>>> IMPORTANT: if you fix the issue, please add the following tag to
>>>>> the commit: Reported-by:
>>>>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>
>>>>> ==================================================================
>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
>>>>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
>>>>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
>>>>> kernel/locking/spinlock.c:170 Read of size 1 at addr
>>>>> ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>
>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
>>>>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
>>>>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
>>>>> io_fallback_req_func Call Trace: <TASK>
>>>>>  __dump_stack lib/dump_stack.c:94 [inline]
>>>>>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>  print_address_description mm/kasan/report.c:378 [inline]
>>>>>  print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>  kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>  spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>>  io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>  io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>  process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>  kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>  </TASK>
>>>>>
>>>>> Allocated by task 6154:
>>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>  kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>  kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664
>>>>> [inline] __comedi_device_postconfig drivers/comedi/drivers.c:721
>>>>> [inline] comedi_device_postconfig+0x2cb/0xc80
>>>>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
>>>>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
>>>>> drivers/comedi/comedi_fops.c:855
>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> Freed by task 6156:
>>>>>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>  poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>  kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>  slab_free_hook mm/slub.c:2381 [inline]
>>>>>  slab_free mm/slub.c:4643 [inline]
>>>>>  kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171
>>>>> [inline] comedi_device_detach+0x2a4/0x9e0
>>>>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
>>>>> drivers/comedi/comedi_fops.c:833
>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>  entry_SYSCALL_64_after_hwframe+0x77/0x7f  
>>>>
>>>> I took a quick look at this, and surely looks like a comedi bug.
>>>> If you call the ioctl part (do_devconfig_ioctl()) with a NULL arg,
>>>> it just does a detach and frees the device, regardless of whether
>>>> anyone has it opened or not?! It's got some odd notion of checking
>>>> whether it's busy or not. For this case, someone has a poll active
>>>> on the device, yet it still happily frees it.
>>>>
>>>> CC'ing some folks, as this looks utterly broken.  
>>>
>>> Case in point, I added:
>>>
>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>> index 376130bfba8a..4d5fde012558 100644
>>> --- a/drivers/comedi/drivers.c
>>> +++ b/drivers/comedi/drivers.c
>>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct
>>> comedi_device *dev) kfree(s->private);
>>>  			comedi_free_subdevice_minor(s);
>>>  			if (s->async) {
>>> +
>>> WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>> comedi_buf_alloc(dev, s, 0); kfree(s->async);
>>>  			}
>>>
>>> and this is the first thing that triggers:
>>>
>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
>>> comedi_device_detach+0x510/0x720 Modules linked in:
>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
>>> 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
>>> linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
>>> +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
>>> lr : comedi_device_detach+0x1dc/0x720
>>> sp : ffff80008aeb7880
>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>> Call trace:
>>>  comedi_device_detach+0x510/0x720 (P)
>>>  do_devconfig_ioctl+0x37c/0x4b8
>>>  comedi_unlocked_ioctl+0x33c/0x2bd8
>>>  __arm64_sys_ioctl+0x124/0x1a0
>>>  invoke_syscall.constprop.0+0x60/0x2a0
>>>  el0_svc_common.constprop.0+0x148/0x240
>>>  do_el0_svc+0x40/0x60
>>>  el0_svc+0x44/0xe0
>>>  el0t_64_sync_handler+0x104/0x130
>>>  el0t_64_sync+0x170/0x178
>>>
>>> Not sure what the right fix for comedi is here, it'd probably be at
>>> least somewhat saner if it only allowed removal of the device when
>>> the ref count would be 1 (for the ioctl itself). Just ignoring the
>>> file ref and allowing blanket removal seems highly suspicious /
>>> broken.
>>>
>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>
>>> #syz set subsystems: kernel  
>>
>> Something like the below may help, at least it'll tell us the device
>> is busy if there's a poll active on it.
>>
>> #syz test:
>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>> master
>>
>>
>> diff --git a/drivers/comedi/comedi_fops.c
>> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e 100644
>> --- a/drivers/comedi/comedi_fops.c
>> +++ b/drivers/comedi/comedi_fops.c
>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
>> comedi_device *dev) static int is_device_busy(struct comedi_device
>> *dev) {
>>  	struct comedi_subdevice *s;
>> -	int i;
>> +	int i, is_busy = 0;
>>  
>>  	lockdep_assert_held(&dev->mutex);
>>  	if (!dev->attached)
>>  		return 0;
>>  
>> +	/* prevent new polls */
>> +	down_write(&dev->attach_lock);
>> +
>>  	for (i = 0; i < dev->n_subdevices; i++) {
>>  		s = &dev->subdevices[i];
>> -		if (s->busy)
>> -			return 1;
>> -		if (s->async && comedi_buf_is_mmapped(s))
>> -			return 1;
>> +		if (s->busy) {
>> +			is_busy = 1;
>> +			break;
>> +		}
>> +		if (!s->async)
>> +			continue;
>> +		if (comedi_buf_is_mmapped(s) ||
>> +		    waitqueue_active(&s->async->wait_head)) {
>> +			is_busy = 1;
>> +			break;
>> +		}
>>  	}
>> -
>> -	return 0;
>> +	up_write(&dev->attach_lock);
>> +	return is_busy;
>>  }
>>  
>>  /*
>>
> 
> Thanks for your investigation and initial fix. I think dev->attach_lock
> needs to be write-locked before calling is_device_busy() and released
> after comedi_device_detach() (although that also write-locks it, so we
> need to refactor that). Otherwise, someone could get added to the
> wait_head after is_device_busy() returns.

That's fine too, this is what my v2 addressed as well. I don't know
comedi well enough so I was worried about having ->attach_lock held over
comedi_device_cancel_all() -> do_cancel() -> s->cancel() as that appears
to be a new pattern. If you know this is fine, then yes by all means, we
should just hold ->attach_lock over the whole thing and not need a
detaching state.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 13:00         ` Jens Axboe
@ 2025-07-22 13:07           ` Ian Abbott
  2025-07-22 13:31             ` Ian Abbott
  0 siblings, 1 reply; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 13:07 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On 22/07/2025 14:00, Jens Axboe wrote:
> On 7/22/25 6:47 AM, Ian Abbott wrote:
>> On Sun, 20 Jul 2025 13:00:59 -0600
>> Jens Axboe <axboe@kernel.dk> wrote:
>>
>>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>>>> Hello,
>>>>>>
>>>>>> syzbot found the following issue on:
>>>>>>
>>>>>> HEAD commit:    4871b7cb27f4 Merge tag
>>>>>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
>>>>>> console output:
>>>>>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
>>>>>> config:
>>>>>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>>> dashboard link:
>>>>>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
>>>>>> Binutils for Debian) 2.40 syz repro:
>>>>>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
>>>>>> reproducer:
>>>>>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>>
>>>>>> Downloadable assets:
>>>>>> disk image (non-bootable):
>>>>>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>>> vmlinux:
>>>>>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>>> kernel image:
>>>>>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>>
>>>>>> IMPORTANT: if you fix the issue, please add the following tag to
>>>>>> the commit: Reported-by:
>>>>>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>>
>>>>>> ==================================================================
>>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
>>>>>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
>>>>>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
>>>>>> kernel/locking/spinlock.c:170 Read of size 1 at addr
>>>>>> ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>>
>>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
>>>>>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
>>>>>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
>>>>>> io_fallback_req_func Call Trace: <TASK>
>>>>>>   __dump_stack lib/dump_stack.c:94 [inline]
>>>>>>   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>>   print_address_description mm/kasan/report.c:378 [inline]
>>>>>>   print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>>   kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>>   __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>>   kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>>   lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>>   lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>>   __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
>>>>>>   _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
>>>>>>   spin_lock_irq include/linux/spinlock.h:376 [inline]
>>>>>>   io_poll_remove_entry io_uring/poll.c:146 [inline]
>>>>>>   io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>>   io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>>   io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>>   io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>>   process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>>   process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>>   worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>>   kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>>   ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>>   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>>   </TASK>
>>>>>>
>>>>>> Allocated by task 6154:
>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>   poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>>   __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>>   kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>>   kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>>   __comedi_device_postconfig_async drivers/comedi/drivers.c:664
>>>>>> [inline] __comedi_device_postconfig drivers/comedi/drivers.c:721
>>>>>> [inline] comedi_device_postconfig+0x2cb/0xc80
>>>>>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
>>>>>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
>>>>>> drivers/comedi/comedi_fops.c:855
>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>
>>>>>> Freed by task 6156:
>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>   kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>>   poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>>   __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>>   kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>>   slab_free_hook mm/slub.c:2381 [inline]
>>>>>>   slab_free mm/slub.c:4643 [inline]
>>>>>>   kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>>   comedi_device_detach_cleanup drivers/comedi/drivers.c:171
>>>>>> [inline] comedi_device_detach+0x2a4/0x9e0
>>>>>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
>>>>>> drivers/comedi/comedi_fops.c:833
>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
>>>>>>   do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>>>>>>   do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
>>>>>>   entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> I took a quick look at this, and surely looks like a comedi bug.
>>>>> If you call the ioctl part (do_devconfig_ioctl()) with a NULL arg,
>>>>> it just does a detach and frees the device, regardless of whether
>>>>> anyone has it opened or not?! It's got some odd notion of checking
>>>>> whether it's busy or not. For this case, someone has a poll active
>>>>> on the device, yet it still happily frees it.
>>>>>
>>>>> CC'ing some folks, as this looks utterly broken.
>>>>
>>>> Case in point, I added:
>>>>
>>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>>> index 376130bfba8a..4d5fde012558 100644
>>>> --- a/drivers/comedi/drivers.c
>>>> +++ b/drivers/comedi/drivers.c
>>>> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct
>>>> comedi_device *dev) kfree(s->private);
>>>>   			comedi_free_subdevice_minor(s);
>>>>   			if (s->async) {
>>>> +
>>>> WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>> comedi_buf_alloc(dev, s, 0); kfree(s->async);
>>>>   			}
>>>>
>>>> and this is the first thing that triggers:
>>>>
>>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
>>>> comedi_device_detach+0x510/0x720 Modules linked in:
>>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
>>>> 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
>>>> linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
>>>> +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
>>>> lr : comedi_device_detach+0x1dc/0x720
>>>> sp : ffff80008aeb7880
>>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>>> Call trace:
>>>>   comedi_device_detach+0x510/0x720 (P)
>>>>   do_devconfig_ioctl+0x37c/0x4b8
>>>>   comedi_unlocked_ioctl+0x33c/0x2bd8
>>>>   __arm64_sys_ioctl+0x124/0x1a0
>>>>   invoke_syscall.constprop.0+0x60/0x2a0
>>>>   el0_svc_common.constprop.0+0x148/0x240
>>>>   do_el0_svc+0x40/0x60
>>>>   el0_svc+0x44/0xe0
>>>>   el0t_64_sync_handler+0x104/0x130
>>>>   el0t_64_sync+0x170/0x178
>>>>
>>>> Not sure what the right fix for comedi is here, it'd probably be at
>>>> least somewhat saner if it only allowed removal of the device when
>>>> the ref count would be 1 (for the ioctl itself). Just ignoring the
>>>> file ref and allowing blanket removal seems highly suspicious /
>>>> broken.
>>>>
>>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>>
>>>> #syz set subsystems: kernel
>>>
>>> Something like the below may help, at least it'll tell us the device
>>> is busy if there's a poll active on it.
>>>
>>> #syz test:
>>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>> master
>>>
>>>
>>> diff --git a/drivers/comedi/comedi_fops.c
>>> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e 100644
>>> --- a/drivers/comedi/comedi_fops.c
>>> +++ b/drivers/comedi/comedi_fops.c
>>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
>>> comedi_device *dev) static int is_device_busy(struct comedi_device
>>> *dev) {
>>>   	struct comedi_subdevice *s;
>>> -	int i;
>>> +	int i, is_busy = 0;
>>>   
>>>   	lockdep_assert_held(&dev->mutex);
>>>   	if (!dev->attached)
>>>   		return 0;
>>>   
>>> +	/* prevent new polls */
>>> +	down_write(&dev->attach_lock);
>>> +
>>>   	for (i = 0; i < dev->n_subdevices; i++) {
>>>   		s = &dev->subdevices[i];
>>> -		if (s->busy)
>>> -			return 1;
>>> -		if (s->async && comedi_buf_is_mmapped(s))
>>> -			return 1;
>>> +		if (s->busy) {
>>> +			is_busy = 1;
>>> +			break;
>>> +		}
>>> +		if (!s->async)
>>> +			continue;
>>> +		if (comedi_buf_is_mmapped(s) ||
>>> +		    waitqueue_active(&s->async->wait_head)) {
>>> +			is_busy = 1;
>>> +			break;
>>> +		}
>>>   	}
>>> -
>>> -	return 0;
>>> +	up_write(&dev->attach_lock);
>>> +	return is_busy;
>>>   }
>>>   
>>>   /*
>>>
>>
>> Thanks for your investigation and initial fix. I think dev->attach_lock
>> needs to be write-locked before calling is_device_busy() and released
>> after comedi_device_detach() (although that also write-locks it, so we
>> need to refactor that). Otherwise, someone could get added to the
>> wait_head after is_device_busy() returns.
> 
> That's fine too, this is what my v2 addressed as well. I don't know
> comedi well enough so I was worried about having ->attach_lock held over
> comedi_device_cancel_all() -> do_cancel() -> s->cancel() as that appears
> to be a new pattern. If you know this is fine, then yes by all means, we
> should just hold ->attach_lock over the whole thing and not need a
> detaching state.

I think it's fine. do_cancel() (and s->cancel()) do not use attach_lock.

Actually, I was thinking it might be safer just to move the 
`wait_queue_head_t wait_head;` member out of `struct comedi_async` and 
into `struct comedi_subdevice`, then it should not matter if there are 
any transient poll_wait() callers waiting on it.

-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [kernel] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:47 ` Jens Axboe
@ 2025-07-22 13:14   ` syzbot
  0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-07-22 13:14 UTC (permalink / raw)
  To: axboe, io-uring, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
Tested-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com

Tested on:

commit:         89be9a83 Linux 6.16-rc7
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=16ee5f22580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=186272c644ef9aa3
dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=15cf24f0580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 13:07           ` Ian Abbott
@ 2025-07-22 13:31             ` Ian Abbott
  2025-07-22 13:50               ` Jens Axboe
  0 siblings, 1 reply; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 13:31 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On Tue, 22 Jul 2025 14:07:45 +0100
Ian Abbott <abbotti@mev.co.uk> wrote:

> On 22/07/2025 14:00, Jens Axboe wrote:
> > On 7/22/25 6:47 AM, Ian Abbott wrote:  
> >> On Sun, 20 Jul 2025 13:00:59 -0600
> >> Jens Axboe <axboe@kernel.dk> wrote:
> >>  
> >>> On 7/20/25 12:49 PM, Jens Axboe wrote:  
> >>>> On 7/20/25 12:24 PM, Jens Axboe wrote:  
> >>>>> On 7/19/25 11:29 AM, syzbot wrote:  
> >>>>>> Hello,
> >>>>>>
> >>>>>> syzbot found the following issue on:
> >>>>>>
> >>>>>> HEAD commit:    4871b7cb27f4 Merge tag
> >>>>>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
> >>>>>> console output:
> >>>>>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
> >>>>>> config:
> >>>>>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> >>>>>> dashboard link:
> >>>>>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> >>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
> >>>>>> Binutils for Debian) 2.40 syz repro:
> >>>>>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
> >>>>>> reproducer:
> >>>>>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
> >>>>>>
> >>>>>> Downloadable assets:
> >>>>>> disk image (non-bootable):
> >>>>>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
> >>>>>> vmlinux:
> >>>>>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
> >>>>>> kernel image:
> >>>>>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
> >>>>>>
> >>>>>> IMPORTANT: if you fix the issue, please add the following tag
> >>>>>> to the commit: Reported-by:
> >>>>>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
> >>>>>>
> >>>>>> ==================================================================
> >>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
> >>>>>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
> >>>>>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
> >>>>>> kernel/locking/spinlock.c:170 Read of size 1 at addr
> >>>>>> ffff88803c6f42b0 by task kworker/2:2/1339
> >>>>>>
> >>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
> >>>>>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
> >>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
> >>>>>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
> >>>>>> io_fallback_req_func Call Trace: <TASK>
> >>>>>>   __dump_stack lib/dump_stack.c:94 [inline]
> >>>>>>   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
> >>>>>>   print_address_description mm/kasan/report.c:378 [inline]
> >>>>>>   print_report+0xcd/0x610 mm/kasan/report.c:480
> >>>>>>   kasan_report+0xe0/0x110 mm/kasan/report.c:593
> >>>>>>   __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
> >>>>>>   kasan_check_byte include/linux/kasan.h:399 [inline]
> >>>>>>   lock_acquire kernel/locking/lockdep.c:5845 [inline]
> >>>>>>   lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
> >>>>>>   __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119
> >>>>>> [inline] _raw_spin_lock_irq+0x36/0x50
> >>>>>> kernel/locking/spinlock.c:170 spin_lock_irq
> >>>>>> include/linux/spinlock.h:376 [inline] io_poll_remove_entry
> >>>>>> io_uring/poll.c:146 [inline]
> >>>>>> io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
> >>>>>> io_poll_remove_entries io_uring/poll.c:159 [inline]
> >>>>>> io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
> >>>>>> io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
> >>>>>> process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
> >>>>>> process_scheduled_works kernel/workqueue.c:3321 [inline]
> >>>>>> worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
> >>>>>> kthread+0x3c5/0x780 kernel/kthread.c:464
> >>>>>> ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
> >>>>>> ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >>>>>> </TASK>
> >>>>>>
> >>>>>> Allocated by task 6154:
> >>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>>>>   poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> >>>>>>   __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
> >>>>>>   kmalloc_noprof include/linux/slab.h:905 [inline]
> >>>>>>   kzalloc_noprof include/linux/slab.h:1039 [inline]
> >>>>>>   __comedi_device_postconfig_async drivers/comedi/drivers.c:664
> >>>>>> [inline] __comedi_device_postconfig
> >>>>>> drivers/comedi/drivers.c:721 [inline]
> >>>>>> comedi_device_postconfig+0x2cb/0xc80
> >>>>>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
> >>>>>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
> >>>>>> drivers/comedi/comedi_fops.c:855
> >>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
> >>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
> >>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
> >>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
> >>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
> >>>>>> [inline] do_syscall_64+0xcd/0x4c0
> >>>>>> arch/x86/entry/syscall_64.c:94
> >>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >>>>>>
> >>>>>> Freed by task 6156:
> >>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>>>>>   kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
> >>>>>>   poison_slab_object mm/kasan/common.c:247 [inline]
> >>>>>>   __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
> >>>>>>   kasan_slab_free include/linux/kasan.h:233 [inline]
> >>>>>>   slab_free_hook mm/slub.c:2381 [inline]
> >>>>>>   slab_free mm/slub.c:4643 [inline]
> >>>>>>   kfree+0x2b4/0x4d0 mm/slub.c:4842
> >>>>>>   comedi_device_detach_cleanup drivers/comedi/drivers.c:171
> >>>>>> [inline] comedi_device_detach+0x2a4/0x9e0
> >>>>>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
> >>>>>> drivers/comedi/comedi_fops.c:833
> >>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
> >>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
> >>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
> >>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
> >>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
> >>>>>> [inline] do_syscall_64+0xcd/0x4c0
> >>>>>> arch/x86/entry/syscall_64.c:94
> >>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f  
> >>>>>
> >>>>> I took a quick look at this, and surely looks like a comedi bug.
> >>>>> If you call the ioctl part (do_devconfig_ioctl()) with a NULL
> >>>>> arg, it just does a detach and frees the device, regardless of
> >>>>> whether anyone has it opened or not?! It's got some odd notion
> >>>>> of checking whether it's busy or not. For this case, someone
> >>>>> has a poll active on the device, yet it still happily frees it.
> >>>>>
> >>>>> CC'ing some folks, as this looks utterly broken.  
> >>>>
> >>>> Case in point, I added:
> >>>>
> >>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
> >>>> index 376130bfba8a..4d5fde012558 100644
> >>>> --- a/drivers/comedi/drivers.c
> >>>> +++ b/drivers/comedi/drivers.c
> >>>> @@ -167,6 +167,7 @@ static void
> >>>> comedi_device_detach_cleanup(struct comedi_device *dev)
> >>>> kfree(s->private); comedi_free_subdevice_minor(s);
> >>>>   			if (s->async) {
> >>>> +
> >>>> WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
> >>>> comedi_buf_alloc(dev, s, 0); kfree(s->async);
> >>>>   			}
> >>>>
> >>>> and this is the first thing that triggers:
> >>>>
> >>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
> >>>> comedi_device_detach+0x510/0x720 Modules linked in:
> >>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
> >>>> 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
> >>>> linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
> >>>> +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
> >>>> lr : comedi_device_detach+0x1dc/0x720
> >>>> sp : ffff80008aeb7880
> >>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
> >>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
> >>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
> >>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
> >>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
> >>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
> >>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
> >>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
> >>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
> >>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
> >>>> Call trace:
> >>>>   comedi_device_detach+0x510/0x720 (P)
> >>>>   do_devconfig_ioctl+0x37c/0x4b8
> >>>>   comedi_unlocked_ioctl+0x33c/0x2bd8
> >>>>   __arm64_sys_ioctl+0x124/0x1a0
> >>>>   invoke_syscall.constprop.0+0x60/0x2a0
> >>>>   el0_svc_common.constprop.0+0x148/0x240
> >>>>   do_el0_svc+0x40/0x60
> >>>>   el0_svc+0x44/0xe0
> >>>>   el0t_64_sync_handler+0x104/0x130
> >>>>   el0t_64_sync+0x170/0x178
> >>>>
> >>>> Not sure what the right fix for comedi is here, it'd probably be
> >>>> at least somewhat saner if it only allowed removal of the device
> >>>> when the ref count would be 1 (for the ioctl itself). Just
> >>>> ignoring the file ref and allowing blanket removal seems highly
> >>>> suspicious / broken.
> >>>>
> >>>> As there's no comedi subsystem in syzbot, moving it to kernel:
> >>>>
> >>>> #syz set subsystems: kernel  
> >>>
> >>> Something like the below may help, at least it'll tell us the
> >>> device is busy if there's a poll active on it.
> >>>
> >>> #syz test:
> >>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> >>> master
> >>>
> >>>
> >>> diff --git a/drivers/comedi/comedi_fops.c
> >>> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e
> >>> 100644 --- a/drivers/comedi/comedi_fops.c
> >>> +++ b/drivers/comedi/comedi_fops.c
> >>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
> >>> comedi_device *dev) static int is_device_busy(struct comedi_device
> >>> *dev) {
> >>>   	struct comedi_subdevice *s;
> >>> -	int i;
> >>> +	int i, is_busy = 0;
> >>>   
> >>>   	lockdep_assert_held(&dev->mutex);
> >>>   	if (!dev->attached)
> >>>   		return 0;
> >>>   
> >>> +	/* prevent new polls */
> >>> +	down_write(&dev->attach_lock);
> >>> +
> >>>   	for (i = 0; i < dev->n_subdevices; i++) {
> >>>   		s = &dev->subdevices[i];
> >>> -		if (s->busy)
> >>> -			return 1;
> >>> -		if (s->async && comedi_buf_is_mmapped(s))
> >>> -			return 1;
> >>> +		if (s->busy) {
> >>> +			is_busy = 1;
> >>> +			break;
> >>> +		}
> >>> +		if (!s->async)
> >>> +			continue;
> >>> +		if (comedi_buf_is_mmapped(s) ||
> >>> +		    waitqueue_active(&s->async->wait_head)) {
> >>> +			is_busy = 1;
> >>> +			break;
> >>> +		}
> >>>   	}
> >>> -
> >>> -	return 0;
> >>> +	up_write(&dev->attach_lock);
> >>> +	return is_busy;
> >>>   }
> >>>   
> >>>   /*
> >>>  
> >>
> >> Thanks for your investigation and initial fix. I think
> >> dev->attach_lock needs to be write-locked before calling
> >> is_device_busy() and released after comedi_device_detach()
> >> (although that also write-locks it, so we need to refactor that).
> >> Otherwise, someone could get added to the wait_head after
> >> is_device_busy() returns.  
> > 
> > That's fine too, this is what my v2 addressed as well. I don't know
> > comedi well enough so I was worried about having ->attach_lock held
> > over comedi_device_cancel_all() -> do_cancel() -> s->cancel() as
> > that appears to be a new pattern. If you know this is fine, then
> > yes by all means, we should just hold ->attach_lock over the whole
> > thing and not need a detaching state.  
> 
> I think it's fine. do_cancel() (and s->cancel()) do not use
> attach_lock.
> 
> Actually, I was thinking it might be safer just to move the 
> `wait_queue_head_t wait_head;` member out of `struct comedi_async`
> and into `struct comedi_subdevice`, then it should not matter if
> there are any transient poll_wait() callers waiting on it.
> 

Moving wait_head out of struct comedi_async:

diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 3383a7ce27ff..f55666ef5d93 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -745,7 +745,7 @@ static void do_become_nonbusy(struct comedi_device *dev,
 		kfree(async->cmd.chanlist);
 		async->cmd.chanlist = NULL;
 		s->busy = NULL;
-		wake_up_interruptible_all(&async->wait_head);
+		wake_up_interruptible_all(&s->async_wait_head);
 	} else {
 		dev_err(dev->class_dev,
 			"BUG: (?) %s called with async=NULL\n", __func__);
@@ -2464,7 +2464,7 @@ static __poll_t comedi_poll(struct file *file, poll_table *wait)
 	s = comedi_file_read_subdevice(file);
 	s_read = s;
 	if (s && s->async) {
-		poll_wait(file, &s->async->wait_head, wait);
+		poll_wait(file, &s->async_wait_head, wait);
 		if (s->busy != file || !comedi_is_subdevice_running(s) ||
 		    (s->async->cmd.flags & CMDF_WRITE) ||
 		    comedi_buf_read_n_available(s) > 0)
@@ -2476,7 +2476,7 @@ static __poll_t comedi_poll(struct file *file, poll_table *wait)
 		unsigned int bps = comedi_bytes_per_sample(s);
 
 		if (s != s_read)
-			poll_wait(file, &s->async->wait_head, wait);
+			poll_wait(file, &s->async_wait_head, wait);
 		if (s->busy != file || !comedi_is_subdevice_running(s) ||
 		    !(s->async->cmd.flags & CMDF_WRITE) ||
 		    comedi_buf_write_n_available(s) >= bps)
@@ -2582,7 +2582,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 		goto out;
 	}
 
-	add_wait_queue(&async->wait_head, &wait);
+	add_wait_queue(&s->async_wait_head, &wait);
 	while (count == 0 && !retval) {
 		unsigned int runflags;
 
@@ -2635,7 +2635,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 
 		buf += n;
 	}
-	remove_wait_queue(&async->wait_head, &wait);
+	remove_wait_queue(&s->async_wait_head, &wait);
 	set_current_state(TASK_RUNNING);
 	if (become_nonbusy && count == 0) {
 		struct comedi_subdevice *new_s;
@@ -2710,7 +2710,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
 		goto out;
 	}
 
-	add_wait_queue(&async->wait_head, &wait);
+	add_wait_queue(&s->async_wait_head, &wait);
 	while (count == 0 && !retval) {
 		set_current_state(TASK_INTERRUPTIBLE);
 
@@ -2762,7 +2762,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
 
 		buf += n;
 	}
-	remove_wait_queue(&async->wait_head, &wait);
+	remove_wait_queue(&s->async_wait_head, &wait);
 	set_current_state(TASK_RUNNING);
 	if (become_nonbusy && count == 0) {
 		struct comedi_subdevice *new_s;
@@ -3289,7 +3289,7 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
 		__comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR);
 
 	if (async->cb_mask & events) {
-		wake_up_interruptible(&async->wait_head);
+		wake_up_interruptible(&s->async_wait_head);
 		si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN;
 	}
 
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index 376130bfba8a..612e8cc8fedb 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -113,6 +113,7 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
 		s->index = i;
 		s->async_dma_dir = DMA_NONE;
 		spin_lock_init(&s->spin_lock);
+		init_waitqueue_head(&s->async_wait_head);
 		s->minor = -1;
 	}
 	return 0;
@@ -665,7 +666,6 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev,
 	if (!async)
 		return -ENOMEM;
 
-	init_waitqueue_head(&async->wait_head);
 	s->async = async;
 
 	async->max_bufsize = comedi_default_buf_maxsize_kb * 1024;
diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedidev.h
index 4cb0400ad616..74f0e7027264 100644
--- a/include/linux/comedi/comedidev.h
+++ b/include/linux/comedi/comedidev.h
@@ -48,6 +48,7 @@
  * @async: Pointer to &struct comedi_async id the subdevice supports
  *	asynchronous acquisition commands.  (Allocated and initialized during
  *	post-configuration if needed.)
+ * @async_wait_head: Task wait queue for file reader or writer.
  * @lock: Pointer to a file object that performed a %COMEDI_LOCK ioctl on the
  *	subdevice.  (Initially NULL.)
  * @busy: Pointer to a file object that is performing an asynchronous
@@ -160,6 +161,7 @@ struct comedi_subdevice {
 	void *private;
 
 	struct comedi_async *async;
+	wait_queue_head_t async_wait_head;
 
 	void *lock;
 	void *busy;
@@ -271,7 +273,6 @@ struct comedi_buf_map {
  * @munge_ptr: Buffer position for "munging".
  * @events: Bit-vector of events that have occurred.
  * @cmd: Details of comedi command in progress.
- * @wait_head: Task wait queue for file reader or writer.
  * @cb_mask: Bit-vector of events that should wake waiting tasks.
  * @inttrig: Software trigger function for command, or NULL.
  *
@@ -356,7 +357,6 @@ struct comedi_async {
 	unsigned int munge_ptr;
 	unsigned int events;
 	struct comedi_cmd cmd;
-	wait_queue_head_t wait_head;
 	unsigned int cb_mask;
 	int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
 		       unsigned int x);



-- 
-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 13:31             ` Ian Abbott
@ 2025-07-22 13:50               ` Jens Axboe
  2025-07-22 14:03                 ` Ian Abbott
  0 siblings, 1 reply; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 13:50 UTC (permalink / raw)
  To: Ian Abbott
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On 7/22/25 7:31 AM, Ian Abbott wrote:
> On Tue, 22 Jul 2025 14:07:45 +0100
> Ian Abbott <abbotti@mev.co.uk> wrote:
> 
>> On 22/07/2025 14:00, Jens Axboe wrote:
>>> On 7/22/25 6:47 AM, Ian Abbott wrote:  
>>>> On Sun, 20 Jul 2025 13:00:59 -0600
>>>> Jens Axboe <axboe@kernel.dk> wrote:
>>>>  
>>>>> On 7/20/25 12:49 PM, Jens Axboe wrote:  
>>>>>> On 7/20/25 12:24 PM, Jens Axboe wrote:  
>>>>>>> On 7/19/25 11:29 AM, syzbot wrote:  
>>>>>>>> Hello,
>>>>>>>>
>>>>>>>> syzbot found the following issue on:
>>>>>>>>
>>>>>>>> HEAD commit:    4871b7cb27f4 Merge tag
>>>>>>>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
>>>>>>>> console output:
>>>>>>>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
>>>>>>>> config:
>>>>>>>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>>>>> dashboard link:
>>>>>>>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
>>>>>>>> Binutils for Debian) 2.40 syz repro:
>>>>>>>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
>>>>>>>> reproducer:
>>>>>>>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>>>>
>>>>>>>> Downloadable assets:
>>>>>>>> disk image (non-bootable):
>>>>>>>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>>>>> vmlinux:
>>>>>>>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>>>>> kernel image:
>>>>>>>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>>>>
>>>>>>>> IMPORTANT: if you fix the issue, please add the following tag
>>>>>>>> to the commit: Reported-by:
>>>>>>>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>>>>
>>>>>>>> ==================================================================
>>>>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
>>>>>>>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
>>>>>>>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
>>>>>>>> kernel/locking/spinlock.c:170 Read of size 1 at addr
>>>>>>>> ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>>>>
>>>>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
>>>>>>>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
>>>>>>>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
>>>>>>>> io_fallback_req_func Call Trace: <TASK>
>>>>>>>>   __dump_stack lib/dump_stack.c:94 [inline]
>>>>>>>>   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>>>>   print_address_description mm/kasan/report.c:378 [inline]
>>>>>>>>   print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>>>>   kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>>>>   __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>>>>   kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>>>>   lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>>>>   lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>>>>   __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119
>>>>>>>> [inline] _raw_spin_lock_irq+0x36/0x50
>>>>>>>> kernel/locking/spinlock.c:170 spin_lock_irq
>>>>>>>> include/linux/spinlock.h:376 [inline] io_poll_remove_entry
>>>>>>>> io_uring/poll.c:146 [inline]
>>>>>>>> io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>>>> io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>>>> io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>>>> io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>>>> process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>>>> process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>>>> worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>>>> kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>>>> ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>>>> ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>>>> </TASK>
>>>>>>>>
>>>>>>>> Allocated by task 6154:
>>>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>>>   poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>>>>   __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>>>>   kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>>>>   kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>>>>   __comedi_device_postconfig_async drivers/comedi/drivers.c:664
>>>>>>>> [inline] __comedi_device_postconfig
>>>>>>>> drivers/comedi/drivers.c:721 [inline]
>>>>>>>> comedi_device_postconfig+0x2cb/0xc80
>>>>>>>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
>>>>>>>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
>>>>>>>> drivers/comedi/comedi_fops.c:855
>>>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
>>>>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
>>>>>>>> [inline] do_syscall_64+0xcd/0x4c0
>>>>>>>> arch/x86/entry/syscall_64.c:94
>>>>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>>>
>>>>>>>> Freed by task 6156:
>>>>>>>>   kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>>>   kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>>>   kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>>>>   poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>>>>   __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>>>>   kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>>>>   slab_free_hook mm/slub.c:2381 [inline]
>>>>>>>>   slab_free mm/slub.c:4643 [inline]
>>>>>>>>   kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>>>>   comedi_device_detach_cleanup drivers/comedi/drivers.c:171
>>>>>>>> [inline] comedi_device_detach+0x2a4/0x9e0
>>>>>>>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
>>>>>>>> drivers/comedi/comedi_fops.c:833
>>>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
>>>>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
>>>>>>>> [inline] do_syscall_64+0xcd/0x4c0
>>>>>>>> arch/x86/entry/syscall_64.c:94
>>>>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f  
>>>>>>>
>>>>>>> I took a quick look at this, and surely looks like a comedi bug.
>>>>>>> If you call the ioctl part (do_devconfig_ioctl()) with a NULL
>>>>>>> arg, it just does a detach and frees the device, regardless of
>>>>>>> whether anyone has it opened or not?! It's got some odd notion
>>>>>>> of checking whether it's busy or not. For this case, someone
>>>>>>> has a poll active on the device, yet it still happily frees it.
>>>>>>>
>>>>>>> CC'ing some folks, as this looks utterly broken.  
>>>>>>
>>>>>> Case in point, I added:
>>>>>>
>>>>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>>>>> index 376130bfba8a..4d5fde012558 100644
>>>>>> --- a/drivers/comedi/drivers.c
>>>>>> +++ b/drivers/comedi/drivers.c
>>>>>> @@ -167,6 +167,7 @@ static void
>>>>>> comedi_device_detach_cleanup(struct comedi_device *dev)
>>>>>> kfree(s->private); comedi_free_subdevice_minor(s);
>>>>>>   			if (s->async) {
>>>>>> +
>>>>>> WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>>>> comedi_buf_alloc(dev, s, 0); kfree(s->async);
>>>>>>   			}
>>>>>>
>>>>>> and this is the first thing that triggers:
>>>>>>
>>>>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
>>>>>> comedi_device_detach+0x510/0x720 Modules linked in:
>>>>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
>>>>>> 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
>>>>>> linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
>>>>>> +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
>>>>>> lr : comedi_device_detach+0x1dc/0x720
>>>>>> sp : ffff80008aeb7880
>>>>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>>>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>>>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>>>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>>>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>>>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>>>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>>>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>>>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>>>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>>>>> Call trace:
>>>>>>   comedi_device_detach+0x510/0x720 (P)
>>>>>>   do_devconfig_ioctl+0x37c/0x4b8
>>>>>>   comedi_unlocked_ioctl+0x33c/0x2bd8
>>>>>>   __arm64_sys_ioctl+0x124/0x1a0
>>>>>>   invoke_syscall.constprop.0+0x60/0x2a0
>>>>>>   el0_svc_common.constprop.0+0x148/0x240
>>>>>>   do_el0_svc+0x40/0x60
>>>>>>   el0_svc+0x44/0xe0
>>>>>>   el0t_64_sync_handler+0x104/0x130
>>>>>>   el0t_64_sync+0x170/0x178
>>>>>>
>>>>>> Not sure what the right fix for comedi is here, it'd probably be
>>>>>> at least somewhat saner if it only allowed removal of the device
>>>>>> when the ref count would be 1 (for the ioctl itself). Just
>>>>>> ignoring the file ref and allowing blanket removal seems highly
>>>>>> suspicious / broken.
>>>>>>
>>>>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>>>>
>>>>>> #syz set subsystems: kernel  
>>>>>
>>>>> Something like the below may help, at least it'll tell us the
>>>>> device is busy if there's a poll active on it.
>>>>>
>>>>> #syz test:
>>>>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>>>> master
>>>>>
>>>>>
>>>>> diff --git a/drivers/comedi/comedi_fops.c
>>>>> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e
>>>>> 100644 --- a/drivers/comedi/comedi_fops.c
>>>>> +++ b/drivers/comedi/comedi_fops.c
>>>>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
>>>>> comedi_device *dev) static int is_device_busy(struct comedi_device
>>>>> *dev) {
>>>>>   	struct comedi_subdevice *s;
>>>>> -	int i;
>>>>> +	int i, is_busy = 0;
>>>>>   
>>>>>   	lockdep_assert_held(&dev->mutex);
>>>>>   	if (!dev->attached)
>>>>>   		return 0;
>>>>>   
>>>>> +	/* prevent new polls */
>>>>> +	down_write(&dev->attach_lock);
>>>>> +
>>>>>   	for (i = 0; i < dev->n_subdevices; i++) {
>>>>>   		s = &dev->subdevices[i];
>>>>> -		if (s->busy)
>>>>> -			return 1;
>>>>> -		if (s->async && comedi_buf_is_mmapped(s))
>>>>> -			return 1;
>>>>> +		if (s->busy) {
>>>>> +			is_busy = 1;
>>>>> +			break;
>>>>> +		}
>>>>> +		if (!s->async)
>>>>> +			continue;
>>>>> +		if (comedi_buf_is_mmapped(s) ||
>>>>> +		    waitqueue_active(&s->async->wait_head)) {
>>>>> +			is_busy = 1;
>>>>> +			break;
>>>>> +		}
>>>>>   	}
>>>>> -
>>>>> -	return 0;
>>>>> +	up_write(&dev->attach_lock);
>>>>> +	return is_busy;
>>>>>   }
>>>>>   
>>>>>   /*
>>>>>  
>>>>
>>>> Thanks for your investigation and initial fix. I think
>>>> dev->attach_lock needs to be write-locked before calling
>>>> is_device_busy() and released after comedi_device_detach()
>>>> (although that also write-locks it, so we need to refactor that).
>>>> Otherwise, someone could get added to the wait_head after
>>>> is_device_busy() returns.  
>>>
>>> That's fine too, this is what my v2 addressed as well. I don't know
>>> comedi well enough so I was worried about having ->attach_lock held
>>> over comedi_device_cancel_all() -> do_cancel() -> s->cancel() as
>>> that appears to be a new pattern. If you know this is fine, then
>>> yes by all means, we should just hold ->attach_lock over the whole
>>> thing and not need a detaching state.  
>>
>> I think it's fine. do_cancel() (and s->cancel()) do not use
>> attach_lock.
>>
>> Actually, I was thinking it might be safer just to move the 
>> `wait_queue_head_t wait_head;` member out of `struct comedi_async`
>> and into `struct comedi_subdevice`, then it should not matter if
>> there are any transient poll_wait() callers waiting on it.
>>
> 
> Moving wait_head out of struct comedi_async:

Not sure that's going to help, surely the device is going away as well,
not just the async part?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 12:47       ` Ian Abbott
  2025-07-22 13:00         ` Jens Axboe
@ 2025-07-22 13:53         ` Jens Axboe
  2025-07-22 14:15           ` Ian Abbott
  1 sibling, 1 reply; 26+ messages in thread
From: Jens Axboe @ 2025-07-22 13:53 UTC (permalink / raw)
  To: Ian Abbott
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

> Thanks for your investigation and initial fix. I think dev->attach_lock
> needs to be write-locked before calling is_device_busy() and released
> after comedi_device_detach() (although that also write-locks it, so we
> need to refactor that). Otherwise, someone could get added to the
> wait_head after is_device_busy() returns.

Looked at this one post coffee, and this looks good to me. If the
->cancel() part is all fine with attach_lock being held, this looks like
the simplest solution to the issue.

I still think the whole busy notion etc needs rethinking in comedi, it
should follow a more idiomatic approach rather than be special. But
that's really separate from this fix.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 13:50               ` Jens Axboe
@ 2025-07-22 14:03                 ` Ian Abbott
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 14:03 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On 22/07/2025 14:50, Jens Axboe wrote:
> On 7/22/25 7:31 AM, Ian Abbott wrote:
>> On Tue, 22 Jul 2025 14:07:45 +0100
>> Ian Abbott <abbotti@mev.co.uk> wrote:
>>
>>> On 22/07/2025 14:00, Jens Axboe wrote:
>>>> On 7/22/25 6:47 AM, Ian Abbott wrote:
>>>>> On Sun, 20 Jul 2025 13:00:59 -0600
>>>>> Jens Axboe <axboe@kernel.dk> wrote:
>>>>>   
>>>>>> On 7/20/25 12:49 PM, Jens Axboe wrote:
>>>>>>> On 7/20/25 12:24 PM, Jens Axboe wrote:
>>>>>>>> On 7/19/25 11:29 AM, syzbot wrote:
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> syzbot found the following issue on:
>>>>>>>>>
>>>>>>>>> HEAD commit:    4871b7cb27f4 Merge tag
>>>>>>>>> 'v6.16-rc6-smb3-client-fixes' of gi.. git tree:       upstream
>>>>>>>>> console output:
>>>>>>>>> https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000 kernel
>>>>>>>>> config:
>>>>>>>>> https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
>>>>>>>>> dashboard link:
>>>>>>>>> https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
>>>>>>>>> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU
>>>>>>>>> Binutils for Debian) 2.40 syz repro:
>>>>>>>>> https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000 C
>>>>>>>>> reproducer:
>>>>>>>>> https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
>>>>>>>>>
>>>>>>>>> Downloadable assets:
>>>>>>>>> disk image (non-bootable):
>>>>>>>>> https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
>>>>>>>>> vmlinux:
>>>>>>>>> https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
>>>>>>>>> kernel image:
>>>>>>>>> https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
>>>>>>>>>
>>>>>>>>> IMPORTANT: if you fix the issue, please add the following tag
>>>>>>>>> to the commit: Reported-by:
>>>>>>>>> syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
>>>>>>>>>
>>>>>>>>> ==================================================================
>>>>>>>>> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq
>>>>>>>>> include/linux/spinlock_api_smp.h:119 [inline] BUG: KASAN:
>>>>>>>>> slab-use-after-free in _raw_spin_lock_irq+0x36/0x50
>>>>>>>>> kernel/locking/spinlock.c:170 Read of size 1 at addr
>>>>>>>>> ffff88803c6f42b0 by task kworker/2:2/1339
>>>>>>>>>
>>>>>>>>> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted
>>>>>>>>> 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
>>>>>>>>> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
>>>>>>>>> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events
>>>>>>>>> io_fallback_req_func Call Trace: <TASK>
>>>>>>>>>    __dump_stack lib/dump_stack.c:94 [inline]
>>>>>>>>>    dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
>>>>>>>>>    print_address_description mm/kasan/report.c:378 [inline]
>>>>>>>>>    print_report+0xcd/0x610 mm/kasan/report.c:480
>>>>>>>>>    kasan_report+0xe0/0x110 mm/kasan/report.c:593
>>>>>>>>>    __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
>>>>>>>>>    kasan_check_byte include/linux/kasan.h:399 [inline]
>>>>>>>>>    lock_acquire kernel/locking/lockdep.c:5845 [inline]
>>>>>>>>>    lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
>>>>>>>>>    __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119
>>>>>>>>> [inline] _raw_spin_lock_irq+0x36/0x50
>>>>>>>>> kernel/locking/spinlock.c:170 spin_lock_irq
>>>>>>>>> include/linux/spinlock.h:376 [inline] io_poll_remove_entry
>>>>>>>>> io_uring/poll.c:146 [inline]
>>>>>>>>> io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
>>>>>>>>> io_poll_remove_entries io_uring/poll.c:159 [inline]
>>>>>>>>> io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
>>>>>>>>> io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
>>>>>>>>> process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
>>>>>>>>> process_scheduled_works kernel/workqueue.c:3321 [inline]
>>>>>>>>> worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
>>>>>>>>> kthread+0x3c5/0x780 kernel/kthread.c:464
>>>>>>>>> ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
>>>>>>>>> ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>>>>>>>>> </TASK>
>>>>>>>>>
>>>>>>>>> Allocated by task 6154:
>>>>>>>>>    kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>>>>    kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>>>>    poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>>>>>>>>>    __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
>>>>>>>>>    kmalloc_noprof include/linux/slab.h:905 [inline]
>>>>>>>>>    kzalloc_noprof include/linux/slab.h:1039 [inline]
>>>>>>>>>    __comedi_device_postconfig_async drivers/comedi/drivers.c:664
>>>>>>>>> [inline] __comedi_device_postconfig
>>>>>>>>> drivers/comedi/drivers.c:721 [inline]
>>>>>>>>> comedi_device_postconfig+0x2cb/0xc80
>>>>>>>>> drivers/comedi/drivers.c:756 comedi_device_attach+0x3cf/0x900
>>>>>>>>> drivers/comedi/drivers.c:998 do_devconfig_ioctl+0x1a7/0x580
>>>>>>>>> drivers/comedi/comedi_fops.c:855
>>>>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
>>>>>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
>>>>>>>>> [inline] do_syscall_64+0xcd/0x4c0
>>>>>>>>> arch/x86/entry/syscall_64.c:94
>>>>>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>>>>
>>>>>>>>> Freed by task 6156:
>>>>>>>>>    kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
>>>>>>>>>    kasan_save_track+0x14/0x30 mm/kasan/common.c:68
>>>>>>>>>    kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
>>>>>>>>>    poison_slab_object mm/kasan/common.c:247 [inline]
>>>>>>>>>    __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
>>>>>>>>>    kasan_slab_free include/linux/kasan.h:233 [inline]
>>>>>>>>>    slab_free_hook mm/slub.c:2381 [inline]
>>>>>>>>>    slab_free mm/slub.c:4643 [inline]
>>>>>>>>>    kfree+0x2b4/0x4d0 mm/slub.c:4842
>>>>>>>>>    comedi_device_detach_cleanup drivers/comedi/drivers.c:171
>>>>>>>>> [inline] comedi_device_detach+0x2a4/0x9e0
>>>>>>>>> drivers/comedi/drivers.c:208 do_devconfig_ioctl+0x46c/0x580
>>>>>>>>> drivers/comedi/comedi_fops.c:833
>>>>>>>>> comedi_unlocked_ioctl+0x15bb/0x2e90
>>>>>>>>> drivers/comedi/comedi_fops.c:2136 vfs_ioctl fs/ioctl.c:51
>>>>>>>>> [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl
>>>>>>>>> fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18e/0x210
>>>>>>>>> fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63
>>>>>>>>> [inline] do_syscall_64+0xcd/0x4c0
>>>>>>>>> arch/x86/entry/syscall_64.c:94
>>>>>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>>>>
>>>>>>>> I took a quick look at this, and surely looks like a comedi bug.
>>>>>>>> If you call the ioctl part (do_devconfig_ioctl()) with a NULL
>>>>>>>> arg, it just does a detach and frees the device, regardless of
>>>>>>>> whether anyone has it opened or not?! It's got some odd notion
>>>>>>>> of checking whether it's busy or not. For this case, someone
>>>>>>>> has a poll active on the device, yet it still happily frees it.
>>>>>>>>
>>>>>>>> CC'ing some folks, as this looks utterly broken.
>>>>>>>
>>>>>>> Case in point, I added:
>>>>>>>
>>>>>>> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
>>>>>>> index 376130bfba8a..4d5fde012558 100644
>>>>>>> --- a/drivers/comedi/drivers.c
>>>>>>> +++ b/drivers/comedi/drivers.c
>>>>>>> @@ -167,6 +167,7 @@ static void
>>>>>>> comedi_device_detach_cleanup(struct comedi_device *dev)
>>>>>>> kfree(s->private); comedi_free_subdevice_minor(s);
>>>>>>>    			if (s->async) {
>>>>>>> +
>>>>>>> WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>>>>>>> comedi_buf_alloc(dev, s, 0); kfree(s->async);
>>>>>>>    			}
>>>>>>>
>>>>>>> and this is the first thing that triggers:
>>>>>>>
>>>>>>> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170
>>>>>>> comedi_device_detach+0x510/0x720 Modules linked in:
>>>>>>> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted
>>>>>>> 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE Hardware name:
>>>>>>> linux,dummy-virt (DT) pstate: 21400005 (nzCv daif +PAN -UAO -TCO
>>>>>>> +DIT -SSBS BTYPE=--) pc : comedi_device_detach+0x510/0x720
>>>>>>> lr : comedi_device_detach+0x1dc/0x720
>>>>>>> sp : ffff80008aeb7880
>>>>>>> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
>>>>>>> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
>>>>>>> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
>>>>>>> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
>>>>>>> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
>>>>>>> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
>>>>>>> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
>>>>>>> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
>>>>>>> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
>>>>>>> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
>>>>>>> Call trace:
>>>>>>>    comedi_device_detach+0x510/0x720 (P)
>>>>>>>    do_devconfig_ioctl+0x37c/0x4b8
>>>>>>>    comedi_unlocked_ioctl+0x33c/0x2bd8
>>>>>>>    __arm64_sys_ioctl+0x124/0x1a0
>>>>>>>    invoke_syscall.constprop.0+0x60/0x2a0
>>>>>>>    el0_svc_common.constprop.0+0x148/0x240
>>>>>>>    do_el0_svc+0x40/0x60
>>>>>>>    el0_svc+0x44/0xe0
>>>>>>>    el0t_64_sync_handler+0x104/0x130
>>>>>>>    el0t_64_sync+0x170/0x178
>>>>>>>
>>>>>>> Not sure what the right fix for comedi is here, it'd probably be
>>>>>>> at least somewhat saner if it only allowed removal of the device
>>>>>>> when the ref count would be 1 (for the ioctl itself). Just
>>>>>>> ignoring the file ref and allowing blanket removal seems highly
>>>>>>> suspicious / broken.
>>>>>>>
>>>>>>> As there's no comedi subsystem in syzbot, moving it to kernel:
>>>>>>>
>>>>>>> #syz set subsystems: kernel
>>>>>>
>>>>>> Something like the below may help, at least it'll tell us the
>>>>>> device is busy if there's a poll active on it.
>>>>>>
>>>>>> #syz test:
>>>>>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>>>>> master
>>>>>>
>>>>>>
>>>>>> diff --git a/drivers/comedi/comedi_fops.c
>>>>>> b/drivers/comedi/comedi_fops.c index 3383a7ce27ff..ea96bc4b818e
>>>>>> 100644 --- a/drivers/comedi/comedi_fops.c
>>>>>> +++ b/drivers/comedi/comedi_fops.c
>>>>>> @@ -785,21 +785,31 @@ void comedi_device_cancel_all(struct
>>>>>> comedi_device *dev) static int is_device_busy(struct comedi_device
>>>>>> *dev) {
>>>>>>    	struct comedi_subdevice *s;
>>>>>> -	int i;
>>>>>> +	int i, is_busy = 0;
>>>>>>    
>>>>>>    	lockdep_assert_held(&dev->mutex);
>>>>>>    	if (!dev->attached)
>>>>>>    		return 0;
>>>>>>    
>>>>>> +	/* prevent new polls */
>>>>>> +	down_write(&dev->attach_lock);
>>>>>> +
>>>>>>    	for (i = 0; i < dev->n_subdevices; i++) {
>>>>>>    		s = &dev->subdevices[i];
>>>>>> -		if (s->busy)
>>>>>> -			return 1;
>>>>>> -		if (s->async && comedi_buf_is_mmapped(s))
>>>>>> -			return 1;
>>>>>> +		if (s->busy) {
>>>>>> +			is_busy = 1;
>>>>>> +			break;
>>>>>> +		}
>>>>>> +		if (!s->async)
>>>>>> +			continue;
>>>>>> +		if (comedi_buf_is_mmapped(s) ||
>>>>>> +		    waitqueue_active(&s->async->wait_head)) {
>>>>>> +			is_busy = 1;
>>>>>> +			break;
>>>>>> +		}
>>>>>>    	}
>>>>>> -
>>>>>> -	return 0;
>>>>>> +	up_write(&dev->attach_lock);
>>>>>> +	return is_busy;
>>>>>>    }
>>>>>>    
>>>>>>    /*
>>>>>>   
>>>>>
>>>>> Thanks for your investigation and initial fix. I think
>>>>> dev->attach_lock needs to be write-locked before calling
>>>>> is_device_busy() and released after comedi_device_detach()
>>>>> (although that also write-locks it, so we need to refactor that).
>>>>> Otherwise, someone could get added to the wait_head after
>>>>> is_device_busy() returns.
>>>>
>>>> That's fine too, this is what my v2 addressed as well. I don't know
>>>> comedi well enough so I was worried about having ->attach_lock held
>>>> over comedi_device_cancel_all() -> do_cancel() -> s->cancel() as
>>>> that appears to be a new pattern. If you know this is fine, then
>>>> yes by all means, we should just hold ->attach_lock over the whole
>>>> thing and not need a detaching state.
>>>
>>> I think it's fine. do_cancel() (and s->cancel()) do not use
>>> attach_lock.
>>>
>>> Actually, I was thinking it might be safer just to move the
>>> `wait_queue_head_t wait_head;` member out of `struct comedi_async`
>>> and into `struct comedi_subdevice`, then it should not matter if
>>> there are any transient poll_wait() callers waiting on it.
>>>
>>
>> Moving wait_head out of struct comedi_async:
> 
> Not sure that's going to help, surely the device is going away as well,
> not just the async part?

Yes, you're right. At least the subdevices are going away, which is just 
as bad as the async structure going away.

-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-22 13:53         ` Jens Axboe
@ 2025-07-22 14:15           ` Ian Abbott
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Abbott @ 2025-07-22 14:15 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs, hsweeten,
	Greg Kroah-Hartman

On 22/07/2025 14:53, Jens Axboe wrote:
>> Thanks for your investigation and initial fix. I think dev->attach_lock
>> needs to be write-locked before calling is_device_busy() and released
>> after comedi_device_detach() (although that also write-locks it, so we
>> need to refactor that). Otherwise, someone could get added to the
>> wait_head after is_device_busy() returns.
> 
> Looked at this one post coffee, and this looks good to me. If the
> ->cancel() part is all fine with attach_lock being held, this looks like
> the simplest solution to the issue.
> 
> I still think the whole busy notion etc needs rethinking in comedi, it
> should follow a more idiomatic approach rather than be special. But
> that's really separate from this fix.
> 

The reason for the separate dev->attach_lock and dev->mutex is to reduce 
the latency for read() and write() operations because dev->mutex can 
sometimes be locked for quite a while when processing the 
COMEDI_INSNLIST ioctl command, for example.  (At some point, I want to 
make the COMEDI_BUFINFO ioctl use dev->attach_lock instead of 
dev->mutex, because that is used when using mmap() instead of 
read()/write().)

-- 
-=( Ian Abbott <abbotti@mev.co.uk> || MEV Ltd. is a company  )=-
-=( registered in England & Wales.  Regd. number: 02862268.  )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries
  2025-07-20 18:49   ` Jens Axboe
  2025-07-20 19:00     ` Jens Axboe
@ 2025-07-23 14:08     ` Aleksandr Nogikh
  1 sibling, 0 replies; 26+ messages in thread
From: Aleksandr Nogikh @ 2025-07-23 14:08 UTC (permalink / raw)
  To: Jens Axboe; +Cc: syzbot, io-uring, linux-kernel, syzkaller-bugs

On Sun, Jul 20, 2025 at 8:49 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 7/20/25 12:24 PM, Jens Axboe wrote:
> > On 7/19/25 11:29 AM, syzbot wrote:
> >> Hello,
> >>
> >> syzbot found the following issue on:
> >>
> >> HEAD commit:    4871b7cb27f4 Merge tag 'v6.16-rc6-smb3-client-fixes' of gi..
> >> git tree:       upstream
> >> console output: https://syzkaller.appspot.com/x/log.txt?x=1288c38c580000
> >> kernel config:  https://syzkaller.appspot.com/x/.config?x=fa738a4418f051ee
> >> dashboard link: https://syzkaller.appspot.com/bug?extid=01523a0ae5600aef5895
> >> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> >> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1688c38c580000
> >> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=166ed7d4580000
> >>
> >> Downloadable assets:
> >> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-4871b7cb.raw.xz
> >> vmlinux: https://storage.googleapis.com/syzbot-assets/4a9dea51d821/vmlinux-4871b7cb.xz
> >> kernel image: https://storage.googleapis.com/syzbot-assets/f96c723cdfe6/bzImage-4871b7cb.xz
> >>
> >> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> >> Reported-by: syzbot+01523a0ae5600aef5895@syzkaller.appspotmail.com
> >>
> >> ==================================================================
> >> BUG: KASAN: slab-use-after-free in __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> >> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> >> Read of size 1 at addr ffff88803c6f42b0 by task kworker/2:2/1339
> >>
> >> CPU: 2 UID: 0 PID: 1339 Comm: kworker/2:2 Not tainted 6.16.0-rc6-syzkaller-00253-g4871b7cb27f4 #0 PREEMPT(full)
> >> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
> >> Workqueue: events io_fallback_req_func
> >> Call Trace:
> >>  <TASK>
> >>  __dump_stack lib/dump_stack.c:94 [inline]
> >>  dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
> >>  print_address_description mm/kasan/report.c:378 [inline]
> >>  print_report+0xcd/0x610 mm/kasan/report.c:480
> >>  kasan_report+0xe0/0x110 mm/kasan/report.c:593
> >>  __kasan_check_byte+0x36/0x50 mm/kasan/common.c:557
> >>  kasan_check_byte include/linux/kasan.h:399 [inline]
> >>  lock_acquire kernel/locking/lockdep.c:5845 [inline]
> >>  lock_acquire+0xfc/0x350 kernel/locking/lockdep.c:5828
> >>  __raw_spin_lock_irq include/linux/spinlock_api_smp.h:119 [inline]
> >>  _raw_spin_lock_irq+0x36/0x50 kernel/locking/spinlock.c:170
> >>  spin_lock_irq include/linux/spinlock.h:376 [inline]
> >>  io_poll_remove_entry io_uring/poll.c:146 [inline]
> >>  io_poll_remove_entries.part.0+0x14e/0x7e0 io_uring/poll.c:179
> >>  io_poll_remove_entries io_uring/poll.c:159 [inline]
> >>  io_poll_task_func+0x4cd/0x1130 io_uring/poll.c:326
> >>  io_fallback_req_func+0x1c7/0x6d0 io_uring/io_uring.c:259
> >>  process_one_work+0x9cf/0x1b70 kernel/workqueue.c:3238
> >>  process_scheduled_works kernel/workqueue.c:3321 [inline]
> >>  worker_thread+0x6c8/0xf10 kernel/workqueue.c:3402
> >>  kthread+0x3c5/0x780 kernel/kthread.c:464
> >>  ret_from_fork+0x5d4/0x6f0 arch/x86/kernel/process.c:148
> >>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >>  </TASK>
> >>
> >> Allocated by task 6154:
> >>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> >>  __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
> >>  kmalloc_noprof include/linux/slab.h:905 [inline]
> >>  kzalloc_noprof include/linux/slab.h:1039 [inline]
> >>  __comedi_device_postconfig_async drivers/comedi/drivers.c:664 [inline]
> >>  __comedi_device_postconfig drivers/comedi/drivers.c:721 [inline]
> >>  comedi_device_postconfig+0x2cb/0xc80 drivers/comedi/drivers.c:756
> >>  comedi_device_attach+0x3cf/0x900 drivers/comedi/drivers.c:998
> >>  do_devconfig_ioctl+0x1a7/0x580 drivers/comedi/comedi_fops.c:855
> >>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
> >>  vfs_ioctl fs/ioctl.c:51 [inline]
> >>  __do_sys_ioctl fs/ioctl.c:907 [inline]
> >>  __se_sys_ioctl fs/ioctl.c:893 [inline]
> >>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >>
> >> Freed by task 6156:
> >>  kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
> >>  kasan_save_track+0x14/0x30 mm/kasan/common.c:68
> >>  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:576
> >>  poison_slab_object mm/kasan/common.c:247 [inline]
> >>  __kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
> >>  kasan_slab_free include/linux/kasan.h:233 [inline]
> >>  slab_free_hook mm/slub.c:2381 [inline]
> >>  slab_free mm/slub.c:4643 [inline]
> >>  kfree+0x2b4/0x4d0 mm/slub.c:4842
> >>  comedi_device_detach_cleanup drivers/comedi/drivers.c:171 [inline]
> >>  comedi_device_detach+0x2a4/0x9e0 drivers/comedi/drivers.c:208
> >>  do_devconfig_ioctl+0x46c/0x580 drivers/comedi/comedi_fops.c:833
> >>  comedi_unlocked_ioctl+0x15bb/0x2e90 drivers/comedi/comedi_fops.c:2136
> >>  vfs_ioctl fs/ioctl.c:51 [inline]
> >>  __do_sys_ioctl fs/ioctl.c:907 [inline]
> >>  __se_sys_ioctl fs/ioctl.c:893 [inline]
> >>  __x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
> >>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >>  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >
> > I took a quick look at this, and surely looks like a comedi bug. If you
> > call the ioctl part (do_devconfig_ioctl()) with a NULL arg, it just does
> > a detach and frees the device, regardless of whether anyone has it
> > opened or not?! It's got some odd notion of checking whether it's busy
> > or not. For this case, someone has a poll active on the device, yet it
> > still happily frees it.
> >
> > CC'ing some folks, as this looks utterly broken.
>
> Case in point, I added:
>
> diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
> index 376130bfba8a..4d5fde012558 100644
> --- a/drivers/comedi/drivers.c
> +++ b/drivers/comedi/drivers.c
> @@ -167,6 +167,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
>                                 kfree(s->private);
>                         comedi_free_subdevice_minor(s);
>                         if (s->async) {
> +                               WARN_ON_ONCE(waitqueue_active(&s->async->wait_head));
>                                 comedi_buf_alloc(dev, s, 0);
>                                 kfree(s->async);
>                         }
>
> and this is the first thing that triggers:
>
> WARNING: CPU: 1 PID: 807 at drivers/comedi/drivers.c:170 comedi_device_detach+0x510/0x720
> Modules linked in:
> CPU: 1 UID: 0 PID: 807 Comm: comedi Not tainted 6.16.0-rc6-00281-gf4a40a4282f4-dirty #1438 NONE
> Hardware name: linux,dummy-virt (DT)
> pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
> pc : comedi_device_detach+0x510/0x720
> lr : comedi_device_detach+0x1dc/0x720
> sp : ffff80008aeb7880
> x29: ffff80008aeb7880 x28: 1fffe00020251205 x27: ffff000101289028
> x26: ffff00010578a000 x25: ffff000101289000 x24: 0000000000000007
> x23: 1fffe00020af1437 x22: 1fffe00020af1438 x21: 0000000000000000
> x20: 0000000000000000 x19: dfff800000000000 x18: ffff0000db102ec0
> x17: ffff80008208e6dc x16: ffff80008362e120 x15: ffff800080a47c1c
> x14: ffff8000826f5aec x13: ffff8000836a0cc4 x12: ffff700010adcd15
> x11: 1ffff00010adcd14 x10: ffff700010adcd14 x9 : ffff8000836a105c
> x8 : ffff800085bc0cc0 x7 : ffff00000b035b50 x6 : 0000000000000000
> x5 : 0000000000000000 x4 : ffff800080960e08 x3 : 0000000000000001
> x2 : ffff00000b4bf930 x1 : 0000000000000000 x0 : ffff0000d7e2b0d8
> Call trace:
>  comedi_device_detach+0x510/0x720 (P)
>  do_devconfig_ioctl+0x37c/0x4b8
>  comedi_unlocked_ioctl+0x33c/0x2bd8
>  __arm64_sys_ioctl+0x124/0x1a0
>  invoke_syscall.constprop.0+0x60/0x2a0
>  el0_svc_common.constprop.0+0x148/0x240
>  do_el0_svc+0x40/0x60
>  el0_svc+0x44/0xe0
>  el0t_64_sync_handler+0x104/0x130
>  el0t_64_sync+0x170/0x178
>
> Not sure what the right fix for comedi is here, it'd probably be at
> least somewhat saner if it only allowed removal of the device when the
> ref count would be 1 (for the ioctl itself). Just ignoring the file ref
> and allowing blanket removal seems highly suspicious / broken.
>
> As there's no comedi subsystem in syzbot, moving it to kernel:
>
> #syz set subsystems: kernel

FTR now there's, so:

#syz set subsystems: comedi

>
> --
> Jens Axboe

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2025-07-23 14:08 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-19 17:29 [syzbot] [io-uring?] KASAN: slab-use-after-free Read in io_poll_remove_entries syzbot
2025-07-20  0:36 ` Hillf Danton
2025-07-20  0:49   ` syzbot
2025-07-20  1:12 ` Hillf Danton
2025-07-20  1:31   ` syzbot
2025-07-20 18:24 ` Jens Axboe
2025-07-20 18:49   ` Jens Axboe
2025-07-20 19:00     ` Jens Axboe
2025-07-20 19:19       ` [syzbot] [kernel] " syzbot
2025-07-22 12:21       ` [syzbot] [io-uring?] " Jens Axboe
2025-07-22 12:30         ` Ian Abbott
2025-07-22 12:43           ` Jens Axboe
2025-07-22 12:31         ` Greg Kroah-Hartman
2025-07-22 12:44           ` Jens Axboe
2025-07-22 12:47       ` Ian Abbott
2025-07-22 13:00         ` Jens Axboe
2025-07-22 13:07           ` Ian Abbott
2025-07-22 13:31             ` Ian Abbott
2025-07-22 13:50               ` Jens Axboe
2025-07-22 14:03                 ` Ian Abbott
2025-07-22 13:53         ` Jens Axboe
2025-07-22 14:15           ` Ian Abbott
2025-07-23 14:08     ` Aleksandr Nogikh
2025-07-20 18:44 ` Forwarded: " syzbot
2025-07-22 12:47 ` Jens Axboe
2025-07-22 13:14   ` [syzbot] [kernel] " syzbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).