CVE-2026-85033: Bluetooth Classic AVRCP Target: missing TX cleanup on disconnect permanently stalls vendor-dependent responses and leaks them to the next peer
The AVRCP Target role in subsys/bluetooth/host/classic/avrcp.c keeps its vendor-dependent response transmit state in a per-connection object selected by connection index (getavrcptg()), with the per-transfer context (tid, sentlen, and the BTAVRCPTGFLAGTXONGOING flag) stored in the userdata of the queued response netbuf. The AVCTP teardown handler avrcpdisconnected() did not cancel tg->vdrsptxwork and did not release the buffers still queued on tg->vdrsptxpending, so a link drop in the middle of a fragmented response left the buffer on the list with TXONGOING still set.
A remote AVRCP Controller can trigger this deterministically: it issues a vendor-dependent command whose response exceeds one AVRCP fragment (for example GetElementAttributes or GetCapabilities), lets btavrcptgvendortxwork() emit the START fragment, and then drops the ACL link instead of sending REQUESTCONTINUINGRESPONSE. The AVCTP control channel requires an encrypted BR/EDR link (BTSECURITYL2), so the attacker must be a paired peer within radio range; no user interaction is needed.
Because the Target objects are static and reused, the next connection landing on the same connection index finds the stale buffer at the head of vdrsptxpending. Every run of the TX work sees TXONGOING and returns immediately, so all further vendor-dependent responses queue behind the stale head and are never sent — a persistent loss of AVRCP Target function that no timeout clears and only a reboot recovers. Each cycle also leaks one response buffer from a shallow application pool, and a new peer that sends REQUESTCONTINUINGRESPONSE clears the stale TXONGOING via btavrcptgprocesscontinuingcmd(), causing the un-sent remainder of the previous peer's response to be transmitted to it.
The fix cancels tg->vdrsptxwork and unrefs every buffer on tg->vdrsptxpending in avrcpdisconnected(); since the TX context lives in the buffer userdata, releasing the buffers also resets the TX state machine. There is no memory corruption: the pre-fix buffer is leaked with a live reference, so no use-after-free arises.