Where
-Infinity
0
Severity
6.5
Use After Free
AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

The Bluetooth Classic Hands-Free Profile Audio Gateway implementation in subsys/bluetooth/host/classic/hfpag.c keeps its struct bthfpag objects in a static pool indexed by ACL connection index. On link teardown, hfpagdisconnected() cancels ag->txwork and the per-call work items and then clears ag->aclconn, which marks the pool slot as free — but it leaves ag->ongoingcallwork (and ag->slcwork) untouched. The next connection that lands on the same slot enters hfpagcreate(), whose only occupancy test is ag->aclconn, and immediately executes memset(ag, 0, sizeof(struct bthfpag)) followed by kworkinitdelayable(). Zeroing and re-initialising a kworkdelayable whose struct timeout node is still linked into the kernel timeout list leaves the kernel holding a reference to a node with NULL prev/next links.

ag->ongoingcallwork is armed by the remote peer: when a Hands-Free unit sends AT+CIND? during Service Level Connection establishment and the application provides the asynchronous getongoingcall callback, the AG schedules the work for CONFIGBTHFPAGGETONGOINGCALLTIMEOUT milliseconds (default 10000). The timer is cancelled only if the application answers in time via bthfpagongoingcalls(). A peer that sends AT+CIND?, then disconnects the HFP RFCOMM DLC, then immediately re-opens it on the same ACL link, reuses the same pool slot deterministically while the timeout is still pending — the AG's RFCOMM server accept path (hfpagaccept()) calls hfpagcreate() directly, so the remote side drives both teardown and re-creation.

The result is corruption of the kernel's timeout list: sysdlistremove() on the zeroed node performs writes through NULL pointers from the clock-announce path, and rescheduling the re-initialised work re-inserts a node the list already references, creating a cycle that the announce loop walks with interrupts locked. The observable impact is a fault or hang of the whole system, i.e. a denial of service reachable from Bluetooth radio range; no attacker-controlled data is written, so this does not by itself yield code execution. Exposure is limited to builds with CONFIGBTHFPAG (marked experimental and disabled by default) whose application implements the asynchronous getongoingcall callback.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203