linux/drivers/bluetooth
Mingyu Wang e2d19969c8 Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
commit c1bb9336ae upstream.

Vulnerabilities leading to Use-After-Free (UAF) and Null Pointer
Dereference (NPD) conditions were observed in the lifecycle management
of hci_uart.

The primary issue arises because the workqueues (init_ready and
write_work) are only flushed/cancelled if the HCI_UART_PROTO_READY
flag is set during TTY close. If a hangup occurs before setup completes,
hci_uart_tty_close() skips the teardown of these workqueues and
proceeds to free the `hu` struct. When the scheduled work executes
later, it blindly dereferences the freed `hu` struct.

Furthermore, several data races and UAFs were identified in the teardown
sequence:
1. Calling hci_uart_flush() from hci_uart_close() without effectively
   disabling write_work causes a race condition where both can concurrently
   double-free hu->tx_skb. This happens because protocol timers can
   concurrently invoke hci_uart_tx_wakeup() and requeue write_work.
2. Calling hci_free_dev(hdev) before hu->proto->close(hu) causes a UAF
   when vendor specific protocol close callbacks dereference hu->hdev.
3. In the initialization error paths, failing to take the proto_lock
   write lock before clearing PROTO_READY leads to races with active
   readers. Additionally, hci_uart_tty_receive() accesses hu->hdev
   outside the read lock, leading to UAFs if the initialization error
   path frees hdev concurrently.

Fix these synchronization and lifecycle issues by:
1. Re-ordering hci_uart_tty_close() to clear HCI_UART_PROTO_READY first,
   followed immediately by a cancel_work_sync(&hu->write_work). Clearing
   the flag locks out concurrent protocol timers from successfully invoking
   hci_uart_tx_wakeup(), effectively rendering the cancellation permanent
   and preventing the tx_skb double-free.
2. Note: Clearing PROTO_READY early causes hci_uart_close() to skip
   hu->proto->flush(). This is perfectly safe in the tty_close path
   because hu->proto->close() executes shortly after, which intrinsically
   purges all protocol SKB queues and tears down the state.
3. Relocating hu->proto->close(hu) strictly prior to hci_free_dev(hdev)
   across all close and error paths to prevent vendor-level UAFs.
4. Moving the hdev->stat.byte_rx increment in hci_uart_tty_receive()
   inside the proto_lock read-side critical section to safely synchronize
   with device unregistration.
5. Adding cancel_work_sync(&hu->write_work) to hci_uart_close() to safely
   flush the workqueue before hci_uart_flush() is invoked via the HCI core.
6. Utilizing cancel_work_sync() instead of disable_work_sync() across
   all paths to prevent permanently breaking user-space retry capabilities.

Fixes: 3b799254cf ("Bluetooth: hci_uart: Cancel init work before unregistering")
Cc: stable@vger.kernel.org
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2026-06-01 17:35:46 +02:00
..
ath3k.c Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl 2024-07-05 09:14:26 +02:00
bcm203x.c Bluetooth: Use fallthrough pseudo-keyword 2020-07-10 19:09:42 +02:00
bfusb.c Bluetooth: bfusb: fix division by zero in send path 2022-01-16 09:12:43 +01:00
bluecard_cs.c Bluetooth: Use fallthrough pseudo-keyword 2020-07-10 19:09:42 +02:00
bpa10x.c Bluetooth: bpa10x: change return value 2019-09-04 16:11:46 +02:00
bt3c_cs.c Bluetooth: bt3c_cs: Fix obsolete function 2018-09-27 12:57:39 +02:00
btbcm.c Bluetooth: hci_bcm: Fall back to getting bdaddr from EFI if not set 2023-05-24 17:36:46 +01:00
btbcm.h Bluetooth: btbcm: Make btbcm_setup_patchram use btbcm_finalize 2020-04-22 19:43:58 +02:00
btintel.c Bluetooth: btintel: Fixe build regression 2024-04-13 13:01:48 +02:00
btintel.h Bluetooth: btintel: Fix WBS setting for Intel legacy ROM products 2022-04-08 14:23:24 +02:00
btmrvl_debugfs.c Bluetooth: btmrvl: Re-use kstrtol_from_user() 2018-05-30 08:16:05 +02:00
btmrvl_drv.h Bluetooth: btmrvl: Drop unused GPIO includes 2019-01-22 09:51:20 +01:00
btmrvl_main.c Bluetooth: btmrvl_sdio: Implement prevent_wake 2020-06-12 08:38:52 +02:00
btmrvl_sdio.c Bluetooth: btmrvl: Use IRQF_NO_AUTOEN flag in request_irq() 2024-10-17 15:11:20 +02:00
btmrvl_sdio.h btmrvl: add platform specific wakeup interrupt support 2016-05-02 19:26:15 +02:00
btmtksdio.c Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event 2022-07-12 16:35:08 +02:00
btmtkuart.c Bluetooth: btmtkuart: fix recv_buf() return value 2024-01-25 14:52:40 -08:00
btqca.c Bluetooth: qca: fix ROM version reading on WCN3998 chips 2026-04-18 10:33:20 +02:00
btqca.h Bluetooth: qca: fix info leak when fetching fw build id 2024-07-05 09:14:11 +02:00
btqcomsmd.c Bluetooth: btqcomsmd: Fix command timeout after setting BD address 2023-03-30 12:47:50 +02:00
btrsi.c Bluetooth: btrsi: use non-kernel-doc comment for copyright 2021-07-22 16:35:46 +02:00
btrtl.c Bluetooth: btrtl: Prevent potential NULL dereference 2025-05-02 07:44:09 +02:00
btrtl.h Bluetooth: hci_h5: Add RTL8822CS capabilities 2021-06-26 07:12:34 +02:00
btsdio.c Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race condition 2023-09-06 21:28:39 +01:00
btusb.c Bluetooth: btusb: clamp SCO altsetting table indices 2026-04-18 10:33:25 +02:00
dtl1_cs.c networking: add and use skb_put_u8() 2017-06-16 11:48:40 -04:00
h4_recv.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
hci_ag6xx.c Bluetooth: hci_uart: Remove redundant assignment to fw_ptr 2021-06-26 07:52:41 +02:00
hci_ath.c Bluetooth: hci_uart: check for missing tty operations 2019-07-31 13:17:33 -07:00
hci_bcm.c Bluetooth: hci_bcm: Add DT compatible for CYW55572 2022-08-11 13:07:52 +02:00
hci_bcsp.c Bluetooth: bcsp: receive data only if registered 2025-12-07 06:09:24 +09:00
hci_h4.c Bluetooth: hci_h4: Remove a redundant assignment in 'h4_flush()' 2020-02-28 08:43:57 +01:00
hci_h5.c Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave() 2022-12-31 13:14:20 +01:00
hci_intel.c Bluetooth: hci_intel: Add check for platform_driver_register 2022-08-17 14:23:34 +02:00
hci_ldisc.c Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths 2026-06-01 17:35:46 +02:00
hci_ll.c Bluetooth: hci_ll: Fix firmware leak on error path 2026-04-18 10:33:24 +02:00
hci_mrvl.c Bluetooth: hci_uart: check for missing tty operations 2019-07-31 13:17:33 -07:00
hci_nokia.c Bluetooth: nokia: fix value check in nokia_bluetooth_serdev_probe() 2023-09-19 12:22:33 +02:00
hci_qca.c Bluetooth: hci_qca: Cleanup on all setup failures 2026-03-04 07:20:23 -05:00
hci_serdev.c Bluetooth: hci_{ldisc,serdev}: check percpu_init_rwsem() failure 2022-10-26 12:34:44 +02:00
hci_uart.h Bluetooth: hci_uart: Fix another race during initialization 2025-05-02 07:44:07 +02:00
hci_vhci.c Bluetooth: vhci: Fix race when opening vhci device 2023-10-25 11:58:55 +02:00
Kconfig Bluetooth: Add support for virtio transport driver 2021-04-08 12:26:34 +02:00
Makefile Bluetooth: Add support for virtio transport driver 2021-04-08 12:26:34 +02:00
virtio_bt.c Bluetooth: virtio_bt: validate rx pkt_type header length 2026-06-01 17:35:21 +02:00