CVE-2026-97977: Bluetooth: btusb: Fix UAF of btusb_data by rx_work
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: btusb: Fix UAF of btusbdata by rxwork
btusbclose() and btusbflush() cancel data->rxwork with the asynchronous canceldelayedwork(), so if btusbrxwork() is already running on another CPU it keeps running after the cancel returns.
btusbdisconnect() calls hciunregisterdev(), which invokes btusbclose(), and then frees the btusbdata. A still running btusbrxwork() then dereferences the freed data:
while ((skb = skbdequeue(&data->aclq))) data->recvacl(data->hdev, skb);
Use canceldelayedworksync() instead. In btusbclose() the cancel also has to happen after btusbstoptraffic(), otherwise an URB completion racing with the cancel can requeue the work right after it has been waited for.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Replace the asynchronous cancel_delayed_work() calls for data->rx_work in btusb_close() and btusb_flush() with cancel_delayed_work_sync() so btusb_rx_work() has finished before btusb_data is freed.
Event History
Frequently Asked Questions
What systems are exposed to this issue?
Systems using the Linux kernel Bluetooth USB driver (btusb) are exposed when the driver is handling Bluetooth traffic and the device is closed, flushed, or disconnected while its receive work may be running.
What conditions are required to trigger the use-after-free?
The receive worker, btusb_rx_work(), must already be running on another CPU when btusb_close() or btusb_flush() attempts to cancel it, followed by device disconnect and freeing of btusb_data. A racing URB completion can also requeue the work if traffic is not stopped before synchronized cancellation.
Is stopping traffic part of the required fix?
Yes. Synchronized cancellation with cancel_delayed_work_sync() must occur after btusb_stop_traffic() in btusb_close(); otherwise an URB completion can requeue the receive work after cancellation has been waited for.
How can I determine whether the issue is fixed?
Check whether the btusb driver uses cancel_delayed_work_sync() for data->rx_work in btusb_close() and btusb_flush(), and verify that btusb_close() calls btusb_stop_traffic() before synchronously cancelling the receive work.