CVE-2026-82388: Use of a released HFP HF object after a failed RFCOMM connect in the Bluetooth Classic host
bthfphfconnect() in subsys/bluetooth/host/classic/hfphf.c allocates the per-connection HFP Hands-Free object with hfphfcreate(), which starts an SDP discovery by passing the object's embedded hf->sdpparam to btsdpdiscover(). That call links the caller-owned parameter block into the SDP client's request list (session->reqs in subsys/bluetooth/host/classic/sdp.c). If the subsequent btrfcommdlcconnect() then failed, the affected code wiped the entire object with (void)memset(newhf, 0, sizeof(newhf)) while that discovery was still outstanding, zeroing the syssnodet node that is still linked in the SDP client's list along with the request's func, uuid and pool pointers, and zeroing the hf->slcwork work item that may already be queued on the system workqueue. The discovery could not be retracted instead: btsdpdiscovercancel() is declared in include/zephyr/bluetooth/classic/sdp.h but has no implementation.
The failing branch is reachable with peer-supplied input. The documented use of bthfphfconnect() is to pass the RFCOMM channel read out of the remote Audio Gateway's SDP record; neither btsdpgetprotoparam() nor bthfphfconnect() range-checks that value, so a remote device advertising an HFP AG record with an RFCOMM channel outside 1-30 makes btrfcommdlcconnect() return -EINVAL and drives the local device into the wipe. The same branch is reached without any application misuse when the remote peer controls connection timing, for example when the RFCOMM session is in BTRFCOMMSTATEDISCONNECTING or the ACL is dropped between object creation and the RFCOMM call.
Once the object has been wiped, the Bluetooth host continues to use it: sdpclientallocbuf() dereferences session->param->pool, which is now NULL, and the SDP receive paths call session->param->func() through a null function pointer, neither of which is NULL-checked. Because the wipe also clears hf->acl, the pool slot is considered free and a retry or an incoming HFP connection re-appends the same still-linked list node, turning session->reqs into a self-referential list that the host's list walkers never leave. The result is a fault or an unrecoverable hang in the Bluetooth host thread; the stray indirect call is through an all-zero pointer whose target the attacker does not control, so the practical impact is denial of service.
The fix keeps the object allocated and marks it with a new BTHFPHFFLAGRELEASING flag, letting bthfphfdiscovercb() release it once the discovery completes instead of destroying it under the SDP client. Only builds with CONFIGBTCLASSIC and CONFIGBTHFPHF enabled are affected.
Affected Software
Event History
Frequently Asked Questions
What conditions make a device realistically exposed?
A device is exposed when it uses the Bluetooth Classic HFP Hands-Free client path and calls bt_hfp_hf_connect() using RFCOMM channel information obtained from a remote Audio Gateway's SDP record. The failing connection branch is reachable through peer-supplied input.
Does exploitation require authentication or user interaction?
No. The supplied vector lists no privileges required and no user interaction, but access is adjacent-network Bluetooth and exploitation requires high attack complexity.
What happens when the vulnerable connection attempt fails?
If bt_rfcomm_dlc_connect() fails after SDP discovery has started, the code clears an HFP object that remains referenced by the SDP request list and may have queued work. This can cause a use-after-free condition and affects availability; the provided impact vector indicates no confidentiality or integrity impact.
Is there a documented workaround if patching cannot happen immediately?
No workaround is provided in the available data. The description specifically notes that SDP discovery cannot be retracted because bt_sdp_discover_cancel() is declared but has no implementation.