bluetooth: hci_core: Fix use-after-free in vhci_flush().
Subsystems (2)
PATCH 1/1 bluetooth: hci_core: Fix use-after-free in vhci_flush().
From: Kuniyuki Iwashima <[email protected]>
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, vhci_release() calls hci_unregister_dev(), hci_free_dev(), and kfree() for struct vhci_data, which is set to hci_dev->dev->driver_data.
The problem is that there is no synchronisation after unlinking hdev from hci_dev_list in hci_unregister_dev(). 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 hci_dev_reset() under SRCU and wait for its completion in hci_unregister_dev().
Another option would be to restore hci_dev->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 hci_unregister_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().
[0]:
BUG: KASAN: slab-use-after-free in skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] BUG: KASAN: slab-use-after-free in skb_queue_purge_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> dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:408 [inline] print_report+0xd2/0x2b0 mm/kasan/report.c:521 kasan_report+0x118/0x150 mm/kasan/report.c:634 skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937 skb_queue_purge include/linux/skbuff.h:3368 [inline] vhci_flush+0x44/0x50 drivers/bluetooth/hci_vhci.c:69 hci_dev_do_reset net/bluetooth/hci_core.c:552 [inline] hci_dev_reset+0x420/0x5c0 net/bluetooth/hci_core.c:592 sock_do_ioctl+0xd9/0x300 net/socket.c:1190 sock_ioctl+0x576/0x790 net/socket.c:1311 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+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: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4359 kmalloc_noprof include/linux/slab.h:905 [inline] kzalloc_noprof include/linux/slab.h:1039 [inline] vhci_open+0x57/0x360 drivers/bluetooth/hci_vhci.c:635 misc_open+0x2bc/0x330 drivers/char/misc.c:161 chrdev_open+0x4c9/0x5e0 fs/char_dev.c:414 do_dentry_open+0xdf0/0x1970 fs/open.c:964 vfs_open+0x3b/0x340 fs/open.c:1094 do_open fs/namei.c:3887 [inline] path_openat+0x2ee5/0x3830 fs/namei.c:4046 do_filp_open+0x1fa/0x410 fs/namei.c:4073 do_sys_openat2+0x121/0x1c0 fs/open.c:1437 do_sys_open fs/open.c:1452 [inline] __do_sys_openat fs/open.c:1468 [inline] __se_sys_openat fs/open.c:1463 [inline] __x64_sys_openat+0x138/0x170 fs/open.c:1463 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 6535: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x62/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+0x18e/0x440 mm/slub.c:4842 vhci_release+0xbc/0xd0 drivers/bluetooth/hci_vhci.c:671 __fput+0x44c/0xa70 fs/file_table.c:465 task_work_run+0x1d1/0x260 kernel/task_work.c:227 exit_task_work include/linux/task_work.h:40 [inline] do_exit+0x6ad/0x22e0 kernel/exit.c:955 do_group_exit+0x21c/0x2d0 kernel/exit.c:1104 __do_sys_exit_group kernel/exit.c:1115 [inline] __se_sys_exit_group kernel/exit.c:1113 [inline] __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1113 x64_sys_call+0x21ba/0x21c0 arch/x86/include/generated/asm/syscalls_64.h:232 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f The buggy address belongs to the object at ffff88807cb8d800 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 88 bytes inside of
freed 1024-byte region [ffff88807cb8d800, ffff88807cb8dc00)
--- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 40 +++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-)
include/net/bluetooth/hci_core.h +2 -0
@@ -29,6 +29,7 @@#include <linux/idr.h> #include <linux/leds.h> #include <linux/rculist.h> +#include <linux/srcu.h> #include <net/bluetooth/hci.h> #include <net/bluetooth/hci_drv.h>
@@ -347,6 +348,7 @@ struct adv_monitor {struct hci_dev {struct list_head list; +struct srcu_struct srcu;struct mutex lock;struct ida unset_handle_ida;
net/bluetooth/hci_core.c +32 -8
@@ -64,9 +64,9 @@ static DEFINE_IDA(hci_index_ida);/* Get HCI device by index. * Device is held on return. */ -struct hci_dev *hci_dev_get (int index) +static struct hci_dev *__hci_dev_get (int index,int *srcu_index) { -struct hci_dev *hdev =NULL , *d; +struct hci_dev *hdev =NULL ;BT_DBG ("%d" , index);
@@ -74,9 +74,11 @@ struct hci_dev *hci_dev_get(int index)return NULL ;read_lock (&hci_dev_list_lock); -list_for_each_entry (d, &hci_dev_list, list) { -if (d->id == index) { - hdev =hci_dev_hold (d); +list_for_each_entry (hdev, &hci_dev_list, list) { +if (hdev->id == index) { +hci_dev_hold (hdev); +if (srcu_index) + *srcu_index =srcu_read_lock (&hdev->srcu);break ; } }
@@ -84,6 +86,22 @@ struct hci_dev *hci_dev_get(int index)return hdev; } +struct hci_dev *hci_dev_get (int index) +{ +return __hci_dev_get (index,NULL ); +} + +static struct hci_dev *hci_dev_get_srcu (int index,int *srcu_index) +{ +return __hci_dev_get (index, srcu_index); +} + +static void hci_dev_put_srcu (struct hci_dev *hdev,int srcu_index) +{ +srcu_read_unlock (&hdev->srcu, srcu_index); +hci_dev_put (hdev); +} +/* ---- Inquiry support ---- */ bool hci_discovery_active (struct hci_dev *hdev)
@@ -568,9 +586,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)int hci_dev_reset (__u16 dev) {struct hci_dev *hdev; -int err; +int err, srcu_index; - hdev =hci_dev_get (dev); + hdev =hci_dev_get_srcu (dev, &srcu_index);if (!hdev)return -ENODEV ;
@@ -592,7 +610,7 @@ int hci_dev_reset(__u16 dev) err =hci_dev_do_reset (hdev); done: -hci_dev_put (hdev); +hci_dev_put_srcu (hdev, srcu_index);return err; }
@@ -2433,6 +2451,9 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)if (!hdev)return NULL ; +if (init_srcu_struct (&hdev->srcu)) +return NULL ; + hdev->pkt_type = (HCI_DM1 |HCI_DH1 |HCI_HV1 ); hdev->esco_type = (ESCO_HV1 ); hdev->link_mode = (HCI_LM_ACCEPT );
@@ -2678,6 +2699,9 @@ void hci_unregister_dev(struct hci_dev *hdev)list_del (&hdev->list);write_unlock (&hci_dev_list_lock); +synchronize_srcu (&hdev->srcu); +cleanup_srcu_struct (&hdev->srcu); +disable_work_sync (&hdev->rx_work);disable_work_sync (&hdev->cmd_work);disable_work_sync (&hdev->tx_work);
Signature · 1 line
2.49.0
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=972027
---Test result---
Test Summary:
CheckPatch PENDING 0.28 seconds GitLint PENDING 0.32 seconds SubjectPrefix FAIL 0.30 seconds BuildKernel PASS 24.78 seconds CheckAllWarning PASS 27.17 seconds CheckSparse WARNING 30.51 seconds BuildKernel32 PASS 24.54 seconds TestRunnerSetup PASS 461.88 seconds TestRunner_l2cap-tester PASS 24.94 seconds TestRunner_iso-tester FAIL 7.68 seconds TestRunner_bnep-tester PASS 5.92 seconds TestRunner_mgmt-tester PASS 131.78 seconds TestRunner_rfcomm-tester PASS 9.27 seconds TestRunner_sco-tester PASS 14.67 seconds TestRunner_ioctl-tester PASS 11.73 seconds TestRunner_mesh-tester FAIL 7.37 seconds TestRunner_smp-tester PASS 8.45 seconds TestRunner_userchan-tester PASS 6.08 seconds IncrementalBuild PENDING 0.78 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix
Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:net/bluetooth/hci_core.c:85:9: warning: context imbalance in '__hci_dev_get' - different lock contexts for basic blocknet/bluetooth/hci_core.c: note: in included file (through include/linux/notifier.h, include/linux/memory_hotplug.h, include/linux/mmzone.h, include/linux/gfp.h, include/linux/xarray.h, include/linux/radix-tree.h, ...):
##############################
Test: TestRunner_iso-tester - FAIL
Desc: Run iso-tester with test-runner
Output:
No test result found
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 WARNING: CPU: 0 PID: 68 at kernel/workqueue.c:2257 __queue_work+0x93e/0xba0
Total: 10, Passed: 9 (90.0%), Failed: 1, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Failed 0.148 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series Output:
---
Regards,
Linux Bluetooth
Date: Fri, 13 Jun 2025 16:34:02 -0700 (PDT)
From: [email protected]
Quoted 42 lines
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=972027---Test result---
Test Summary:
CheckPatch PENDING 0.28 seconds GitLint PENDING 0.32 seconds SubjectPrefix FAIL 0.30 seconds BuildKernel PASS 24.78 seconds CheckAllWarning PASS 27.17 seconds CheckSparse WARNING 30.51 seconds BuildKernel32 PASS 24.54 seconds TestRunnerSetup PASS 461.88 seconds TestRunner_l2cap-tester PASS 24.94 seconds TestRunner_iso-tester FAIL 7.68 seconds TestRunner_bnep-tester PASS 5.92 seconds TestRunner_mgmt-tester PASS 131.78 seconds TestRunner_rfcomm-tester PASS 9.27 seconds TestRunner_sco-tester PASS 14.67 seconds TestRunner_ioctl-tester PASS 11.73 seconds TestRunner_mesh-tester FAIL 7.37 seconds TestRunner_smp-tester PASS 8.45 seconds TestRunner_userchan-tester PASS 6.08 seconds IncrementalBuild PENDING 0.78 secondsDetails
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
Quoted 5 lines
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix Output:
"Bluetooth: " prefix is not specified in the subject
Will use it in v2.
Quoted 5 lines
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:net/bluetooth/hci_core.c:85:9: warning: context imbalance in '__hci_dev_get' - different lock contexts for basicblocknet/bluetooth/hci_core.c: note: in included file (throughinclude/linux/notifier.h,include/linux/memory_hotplug.h,include/linux/mmzone.h,include/linux/gfp.h,include/linux/xarray.h,include/linux/radix-tree.h, ...):
Do we want to silence sparse by putting acquire()/release() or is this warning acceptable like netdev tree ?
IMHO, sparse doesn't help much and I prefer lockdep.
Quoted 9 lines
##############################
Test: TestRunner_iso-tester - FAIL
Desc: Run iso-tester with test-runner
Output:
No test result found
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Quoted 3 lines
BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 WARNING: CPU: 0 PID: 68 at kernel/workqueue.c:2257 __queue_work+0x93e/0xba0Total: 10, Passed: 9 (90.0%), Failed: 1, Not Run: 0
It seems the same splat can be seen on other patches.
https://lore.kernel.org/linux-bluetooth/?q=KASAN+run_timer_softirq
Is this a known issue, or are we all making the same mistake ?
If latter, can I get the full splat and some guidance to run the same test locally (if it's easy to set up) ?
Thanks
Quoted 13 lines
Failed Test Cases
Mesh - Send cancel - 1 Failed 0.148 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series Output:---
Regards,
Linux Bluetooth
pe, 2025-06-13 kello 19:20 -0700, Kuniyuki Iwashima kirjoitti:
[clip]
Quoted 8 lines
Quoted 7 lines
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 WARNING: CPU: 0 PID: 68 at kernel/workqueue.c:2257 __queue_work+0x93e/0xba0Total: 10, Passed: 9 (90.0%), Failed: 1, Not Run: 0
Quoted 5 lines
It seems the same splat can be seen on other patches.
https://lore.kernel.org/linux-bluetooth/?q=KASAN+run_timer_softirqIs this a known issue, or are we all making the same mistake ? If latter, can I get the full splat
https://github.com/BluezTestBot/bluetooth-next/pull/2887/checks
But probably it's an existing issue.
Quoted 2 lines
and some guidance to run
the same test locally (if it's easy to set up) ?
Please see
https://github.com/bluez/bluez/blob/master/doc/test-runner.rst#examples
I does not reproduce locally for me however.
Signature · 1 line
Pauli Virtanen
From: Pauli Virtanen <[email protected]>
Date: Sat, 14 Jun 2025 14:30:18 +0300
Quoted 14 lines
pe, 2025-06-13 kello 19:20 -0700, Kuniyuki Iwashima kirjoitti:
[clip]
Quoted 11 lines
Quoted 7 lines
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 WARNING: CPU: 0 PID: 68 at kernel/workqueue.c:2257 __queue_work+0x93e/0xba0Total: 10, Passed: 9 (90.0%), Failed: 1, Not Run: 0
It seems the same splat can be seen on other patches.
https://lore.kernel.org/linux-bluetooth/?q=KASAN+run_timer_softirq
Quoted 6 lines
Quoted 2 lines
Is this a known issue, or are we all making the same mistake ? If latter, can I get the full splat
https://github.com/BluezTestBot/bluetooth-next/pull/2887/checks
But probably it's an existing issue.
I agree this is a separate issue.
To me, disable_work_sync(&hdev->rx_work) in hci_unregister_dev() is doing the proper synchronisation between the work, so it might be a problem in the workqueue code.
Quoted 8 lines
Quoted 3 lines
and some guidance to run
the same test locally (if it's easy to set up) ?Please see
https://github.com/bluez/bluez/blob/master/doc/test-runner.rst#examplesI does not reproduce locally for me however.
Thanks!
Dear Kuniyuki,
Thank you for your patch with a well written commit message. Just a minor request to remove the dot/period from the end of the commit message summary.
Am 14.06.25 um 01:02 schrieb Kuniyuki Iwashima:
Quoted 1 line
From: Kuniyuki Iwashima <[email protected]>
[…]
Kind regards,
Paul
From: Paul Menzel <[email protected]>
Date: Sat, 14 Jun 2025 07:38:11 +0200
Quoted 6 lines
Dear Kuniyuki,
Thank you for your patch with a well written commit message. Just a minor request to remove the dot/period from the end of the commit message summary.
Sure, will remove it.
Quoted 7 lines
Am 14.06.25 um 01:02 schrieb Kuniyuki Iwashima:
Quoted 1 line
From: Kuniyuki Iwashima <[email protected]>
[…]
Acked-by Paul Menzel <[email protected]>
Thanks!