CVE-2026-68085
This CVE exposes a state machine synchronization failure in the Linux kernel's HCI UART Bluetooth driver—the kind of bug that emerges when developers treat work queue cancellation as a single atomic operation rather than a two-phase process requiring explicit state cleanup. The vulnerability centers on the HCI_UART_SENDING flag, which is not merely a status indicator but a synchronization primitive coordinating between the work queue subsystem and device lifecycle. When hci_uart_close() called cancel_work_sync() without clearing this flag, it left the device in a logically inconsistent state: the work queue believed it was idle, but the driver still considered itself mid-transmission. Future reopenings of the device would find the flag still set, blocking subsequent writes and rendering the device permanently unresponsive until userspace reinitializes the driver or the system reboots. This is persistent state poisoning, not a transient failure that heals automatically. The fix is instructive on two levels. First, the transition from cancel_work_sync() to disable_work_sync() + enable_work() reflects a fundamental API mismatch: cancel_work_sync() is an abandonment operation (stop and never return), while disable_work_sync() is a suspension operation (pause, let me fix something, then continue). The original code needed the latter but had only the former, so developers improvised with HCI_UART_SENDING as a manual suspension flag—a pattern scattered throughout the kernel wherever drivers needed suspension semantics the API doesn't natively provide. Second, relocating cancellation from hci_uart_close() to hci_uart_flush() respects device lifecycle semantics: closing a device shouldn't flush its queues, but flushing must cancel pending work because the queue purge invalidates what the work item would transmit. This separation of concerns wasn't enforced in the original design. The blast radius matters operationally. The HCI UART proto layer is shared infrastructure inherited by H4, BCSP, LL, and other protocol implementations. One broken close() path can deaden every Bluetooth serial transport using this abstraction. If the invariant around HCI_UART_SENDING wasn't explicit in documentation, other protocol handlers may have independently introduced the same bug—or avoided it only by accident. The pattern of auxiliary state flags decoupled from work item lifetimes is a recurring defect across kernel subsystems (CAN drivers, serial console handlers, USB gadget close paths), not an isolated lapse. Audit your drivers for similar implicit invariants: any code using cancel_work_sync() while maintaining auxiliary state flags tied to work item execution is vulnerable.
Reviewed through automated stages and approved by a human before publication.