In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: hcicore: Fix use-after-free in vhciflush()
syzbot reported use-after-free in vhci_flush() without repro. [0]
From the splat, a thread close()d a vhci file descriptor while its device was being used by iotcl() on another thread.
Once the last fd refcnt is released, vhcirelease() calls hciunregisterdev(), hcifreedev(), and kfree() for struct vhcidata, which is set to hcidev->dev->driverdata.
The problem is that there is no synchronisation after unlinking hdev from hcidevlist in hciunregisterdev(). There might be another thread still accessing the hdev which was fetched before the unlink operation.
We can use SRCU for such synchronisation.
Let's run hcidevreset() under SRCU and wait for its completion in hciunregisterdev().
Another option would be to restore hcidev->destruct(), which was removed in commit 587ae086f6e4 ("Bluetooth: Remove unused hci-destruct cb"). However, this would not be a good solution, as we should not run hciunregister_dev() while there are in-flight ioctl() requests, which could lead to another data-race KCSAN splat.
Note that other drivers seem to have the same problem, for exmaple, virtbt_remove().
BUG: KASAN: slab-use-after-free in skbqueuepurge_reason+0x99/0x360 net/core/skbuff.c:3937 Read of size 8 at addr ffff88807cb8d858 by task syz.1.219/6718
CPU: 1 UID: 0 PID: 6718 Comm: syz.1.219 Not tainted 6.16.0-rc1-syzkaller-00196-g08207f42d3ff #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 Call Trace: <TASK> dumpstacklvl+0x189/0x250 lib/dumpstack.c:120 printaddressdescription mm/kasan/report.c:408 [inline] printreport+0xd2/0x2b0 mm/kasan/report.c:521 kasanreport+0x118/0x150 mm/kasan/report.c:634 skbqueueemptylockless include/linux/skbuff.h:1891 [inline] skbqueuepurgereason+0x99/0x360 net/core/skbuff.c:3937 skbqueuepurge include/linux/skbuff.h:3368 [inline] vhciflush+0x44/0x50 drivers/bluetooth/hcivhci.c:69 hcidevdoreset net/bluetooth/hcicore.c:552 [inline] hcidevreset+0x420/0x5c0 net/bluetooth/hcicore.c:592 sockdoioctl+0xd9/0x300 net/socket.c:1190 sockioctl+0x576/0x790 net/socket.c:1311 vfsioctl fs/ioctl.c:51 [inline] _dosysioctl fs/ioctl.c:907 [inline] _sesysioctl+0xf9/0x170 fs/ioctl.c:893 dosyscallx64 arch/x86/entry/syscall64.c:63 [inline] dosyscall64+0xfa/0x3b0 arch/x86/entry/syscall64.c:94 entrySYSCALL64afterhwframe+0x77/0x7f RIP: 0033:0x7fcf5b98e929 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fcf5c7b9038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007fcf5bbb6160 RCX: 00007fcf5b98e929 RDX: 0000000000000000 RSI: 00000000400448cb RDI: 0000000000000009 RBP: 00007fcf5ba10b39 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007fcf5bbb6160 R15: 00007ffd6353d528 </TASK>
Allocated by task 6535: kasansavestack mm/kasan/common.c:47 [inline] kasansavetrack+0x3e/0x80 mm/kasan/common.c:68 poisonkmallocredzone mm/kasan/common.c:377 [inline] _kasankmalloc+0x93/0xb0 mm/kasan/common.c:394 kasankmalloc include/linux/kasan.h:260 [inline] _kmalloccachenoprof+0x230/0x3d0 mm/slub.c:4359 kmallocnoprof include/linux/slab.h:905 [inline] kzallocnoprof include/linux/slab.h:1039 [inline] vhciopen+0x57/0x360 drivers/bluetooth/hcivhci.c:635 miscopen+0x2bc/0x330 drivers/char/misc.c:161 chrdevopen+0x4c9/0x5e0 fs/chardev.c:414 dodentryopen+0xdf0/0x1970 fs/open.c:964 vfsopen+0x3b/0x340 fs/open.c:1094 doopen fs/namei.c:3887 [inline] pathopenat+0x2ee5/0x3830 fs/name ---truncated---