CVE-2026-74509
The vulnerability sits in the kernel's Bluetooth command-sync layer, where the natural implementation pattern produces a use-after-free. The function `hci_find_adv_instance()` returns a pointer with an implicit lifetime contract—valid only while `hdev->lock` is held—but the type system cannot enforce this and the compiler cannot catch violations. The command-sync architecture creates structural pressure to release locks before waiting for hardware responses: holding `hdev->lock` across a controller round-trip would deadlock the workqueue. The API gives developers no signal that dereferencing this pointer after releasing the lock enters dangerous territory. A pointer is a pointer; the contract lives only in documentation and tribal knowledge. The fix abandons pointer-passing in favor of parameter snapshotting. Rather than passing `adv_info*` across the lock boundary, the patch captures the needed values (instance ID, dirty flags, parameters) under lock, then performs a fresh lookup after waiting. This is the correct pattern, but it requires more boilerplate—the developer must explicitly enumerate what data they need rather than simply dereferencing the structure. The vulnerability occurred because the easy path was the broken path. This points to a systemic issue: the kernel's locking primitives create race windows that only reveal themselves under specific interrupt timing, and the Bluetooth subsystem's dual-threaded architecture (hci_cmd_sync_work vs hci_rx_work) makes these races particularly likely. Beyond this specific fix, multiple hci_sync paths perform lookups under `hdev->lock` and release it before using the results—this race pattern is likely endemic to the subsystem. The deeper problem is that the kernel's fundamental pointer-passing model makes safe ownership transfer the hard path and unsafe dereference the easy path. The fix doesn't change that incentive structure—it just makes the safe path more verbose. Until the API can be refactored to make snapshot-and-relock the path of least resistance, or until explicit lifetime contracts are enforced through tooling, every future developer touching this code will be one forgotten snapshot field away from reintroducing the same class of bug.
Reviewed through automated stages and approved by a human before publication.