CVE-2026-98632: Bluetooth: mgmt: Dequeue pending mesh_send_sync entries on cancel
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: mgmt: Dequeue pending meshsendsync entries on cancel
In sendcancel(), pending meshtx objects are removed from the hdev->meshpending list and freed via meshsendcomplete(). However, if a mesh transmission was already queued onto hdev->cmdsyncworklist via meshnext(), the queued entry retains a raw pointer to meshtx.
When hcicmdsyncwork later processes the entry, it attempts to execute meshsendsync and its destroy callback meshsendstartcomplete using the already freed meshtx pointer, leading to a use-after-free.
Fix this by invoking hcicmdsyncdequeue() for meshsendsync on the target meshtx before completing it. If the entry is found and dequeued, its destroy callback will complete and free the object; otherwise, meshsendcomplete() is called directly.
Additionally, ensure the transmission queue advances after cancellation or errors. In meshsendstartcomplete(), call meshnext() on error unless err is -ECANCELED, because hcicmdsyncdequeue() holds hdev->cmdsyncworklock and calling meshnext() synchronously would deadlock. Instead, advance the queue in sendcancel() once the lock is released and if no transmission is in progress.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
In the Bluetooth mesh transmission cancellation path, invoke hci_cmd_sync_dequeue() for mesh_send_sync, and in send_cancel() advance the queue with mesh_next() after releasing hdev->cmd_sync_work_lock when no transmission is in progress. In mesh_send_start_complete(), call mesh_next() on errors unless err is -ECANCELED, so pending mesh_tx objects are removed from hdev->mesh_pending and completed without leaving queued entries with raw pointers to freed objects.
Event History
Frequently Asked Questions
Which execution path must be present for the use-after-free to occur?
A Bluetooth mesh transmission must have been queued on hdev->cmd_sync_work_list by mesh_next(), then cancelled while its mesh_tx object is still referenced by that queued synchronous command entry. Later processing of that entry can invoke callbacks using the freed object.
What does the fix do when a mesh transmission is cancelled?
It attempts to dequeue the pending mesh_send_sync entry for the target transmission before completing it. If the entry was dequeued, its destroy callback completes and frees the object; otherwise, mesh_send_complete() is called directly, and the transmission queue is advanced after cancellation or applicable errors.