7.8
/ 10
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Description
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
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.
Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
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.
Basic Information
ID
CVE-2026-46275
Source
Linux
Published
Jun 8, 2026 at 14:30
Modified
Jun 14, 2026 at 04:29
Affected Product
Vendor
Linux
Product
Linux
Version
3b799254cf6f481460719023d7a18f46651e5e7f
Affected Versions
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux cd27019bc149f20f12ebec943c2b4c775745a5a0
Linux Linux aea63181b6fcb6b9ccde1ada9ea51be19c4015af
Linux Linux 0d234d1135dcd8876de0576dac68efd0a87eef87
Linux Linux 3fe978892ab46efc2f3830d9abc015eff72caaf9
Linux Linux 0d987e14bebaf0f67ee7dbefaf6165c62cd1d27f
Linux Linux 4.14.203
Linux Linux 4.19.153
Linux Linux 5.4.73
Linux Linux 5.8.17
Linux Linux 5.9.2
Linux Linux 5.10
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux 3b799254cf6f481460719023d7a18f46651e5e7f
Linux Linux cd27019bc149f20f12ebec943c2b4c775745a5a0
Linux Linux aea63181b6fcb6b9ccde1ada9ea51be19c4015af
Linux Linux 0d234d1135dcd8876de0576dac68efd0a87eef87
Linux Linux 3fe978892ab46efc2f3830d9abc015eff72caaf9
Linux Linux 0d987e14bebaf0f67ee7dbefaf6165c62cd1d27f
Linux Linux 4.14.203
Linux Linux 4.19.153
Linux Linux 5.4.73
Linux Linux 5.8.17
Linux Linux 5.9.2
Linux Linux 5.10
References
- git.kernel.org /stable/c/78aad93e938f013d9272fe0ee168f27883afa95c
- git.kernel.org /stable/c/e2d19969c8d9198ecc3090bcd5312ecd503a3339
- git.kernel.org /stable/c/c85cff648a2bc92322912db5f1727ad05afae7b6
- git.kernel.org /stable/c/9d20d48be2c4a071fb015eb09bda2cecd25daf34
- git.kernel.org /stable/c/81c7a3c22a0f2808cf4ae0b4908f59763b23606d
- git.kernel.org /stable/c/192cb0f1ca706d9a1bc36ae0ad5f666d1e4fd894
- git.kernel.org /stable/c/7338031946bd06f6dff149e67b60c4cd083bfea8
- git.kernel.org /stable/c/c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b