In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: use RCU for hciconnparams and iterate safely in hci_sync
hciupdateacceptlistsync iterates over hdev->pendleconns and hdev->pendlereports, and waits for controller events in the loop body, without holding hdev lock.
Meanwhile, these lists and the items may be modified e.g. by lescancleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free).
Use RCU for the hciconnparams action lists. Since the loop bodies in hcisync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READONCE/WRITE_ONCE should guarantee we read valid values.
Free params everywhere with hciconnparams_free so the cleanup is guaranteed to be done properly.
This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hcilesetcigparams to always return false, and running iso-tester:
================================================================== BUG: KASAN: slab-use-after-free in hciupdatepassivescansync (net/bluetooth/hcisync.c:2536 net/bluetooth/hcisync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hcicmdsyncwork Call Trace: <TASK> dumpstacklvl (./arch/x86/include/asm/irqflags.h:134 lib/dumpstack.c:107) printreport (mm/kasan/report.c:320 mm/kasan/report.c:430) ? _virtaddrvalid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hciupdatepassivescansync (net/bluetooth/hcisync.c:2536 net/bluetooth/hcisync.c:2723 net/bluetooth/hcisync.c:2841) kasanreport (mm/kasan/report.c:538) ? hciupdatepassivescansync (net/bluetooth/hcisync.c:2536 net/bluetooth/hcisync.c:2723 net/bluetooth/hcisync.c:2841) hciupdatepassivescansync (net/bluetooth/hcisync.c:2536 net/bluetooth/hcisync.c:2723 net/bluetooth/hcisync.c:2841) ? _pfxhciupdatepassivescansync (net/bluetooth/hcisync.c:2780) ? mutexlock (kernel/locking/mutex.c:282) ? _pfxmutexlock (kernel/locking/mutex.c:282) ? _pfxmutexunlock (kernel/locking/mutex.c:538) ? _pfxupdatepassivescansync (net/bluetooth/hcisync.c:2861) hcicmdsyncwork (net/bluetooth/hcisync.c:306) processonework (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) workerthread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? _pfxworkerthread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? _pfxkthread (kernel/kthread.c:331) retfromfork (arch/x86/entry/entry_64.S:314) </TASK>
Allocated by task 31: kasansavestack (mm/kasan/common.c:46) kasansettrack (mm/kasan/common.c:52) _kasankmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hciconnparamsadd (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hcicore.c:2277) hciconnectlescan (net/bluetooth/hciconn.c:1419 net/bluetooth/hciconn.c:1589) hciconnectcis (net/bluetooth/hciconn.c:2266) isoconnectcis (net/bluetooth/iso.c:390) isosockconnect (net/bluetooth/iso.c:899) _sysconnect (net/socket.c:2003 net/socket.c:2020) _x64sysconnect (net/socket.c:2027) dosyscall64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entrySYSCALL64afterhwframe (arch/x86/entry/entry64.S:120)
Freed by task 15: kasansavestack (mm/kasan/common.c:46) kasansettrack (mm/kasan/common.c:52) kasansavefreeinfo (mm/kasan/generic.c:523) _kasanslabfree (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) _kmemcachefree (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hciconnparamsdel (net/bluetooth/hcicore.c:2323) lescancleanup (net/bluetooth/hciconn.c:202) processonework (./arch/x86/include/asm/preempt. ---truncated---