CVE-2025-22435 AI-generated analysis
platform/packages/modules/Bluetooth, AVDTP signaling (system/stack/avdt)
Adds a check in avdt_msg_ind (system/stack/avdt/avdt_msg.cc) that drops an incoming AVDTP response or reject whose signal id does not match the command currently pending on the CCB (p_ccb->p_curr_cmd->event), or that arrives when no command is pending. This prevents type confusion when the response is parsed.
Root cause
In avdt_msg_ind, for messages that are not a general reject, the signal id (sig) is parsed straight from the incoming packet (AVDT_MSG_PRS_SIG) and only range-checked (1..AVDT_SIG_MAX). For response messages the function then picks a parse target based on that sig. For AVDT_SIG_DISCOVER it casts p_ccb->p_proc_data to tAVDT_SEP_INFO* and uses p_ccb->proc_param as num_seps. For AVDT_SIG_GETCAP and AVDT_SIG_GET_ALLCAP it casts p_ccb->p_proc_data to AvdtpSepConfig*. Nothing checked that the sig in a received RSP or REJ matched the pending command (p_ccb->p_curr_cmd). Per the commit message, a peer could therefore reply to a pending AVDT message with the wrong type, causing type confusion and an eventual OOB access.
How the fix works
- system/stack/avdt/avdt_msg.cc:avdt_msg_ind: a new block is added inside the 'not a general reject' branch, after the existing sig range check. If msg_type is AVDT_MSG_TYPE_RSP or AVDT_MSG_TYPE_REJ, and either p_ccb->p_curr_cmd is nullptr or p_ccb->p_curr_cmd->event != sig, the code logs 'Dropping msg with mismatched sig' and sets ok to false.
- Because ok is false, the following 'if (ok && !gen_rej)' parse block is skipped. That block is the one that chooses the parse target from sig and casts p_ccb->p_proc_data.
- The general-reject path already took sig from p_ccb->p_curr_cmd->event rather than from the packet. The new validation therefore targets the non-general-reject RSP/REJ path.
Completeness
- Covers all RSP and REJ messages in the non-general-reject branch of avdt_msg_ind. In the code shown, this is where sig is taken from the packet and used to choose a p_proc_data cast. The general-reject branch takes sig from p_curr_cmd and is not changed.
- CMD messages are not subject to the new check. Whether any CMD parse path uses p_proc_data is not shown.
- The check compares only the signal id with the pending command, not the transaction label. Any label matching is outside the material.
- The check comes after the sig range check. If sig is out of range, ok is already false and the new check is redundant but harmless.
Behavior changes
- Unsolicited responses and rejects (no pending command), and responses and rejects whose signal id differs from the pending command, are now dropped with a warning log and are not parsed.
- The new block sends nothing to the peer. The message is simply discarded.
Per major
- Android 14: Same fix: commit efa5f4ef386a in android-security-14.0.0_r19, logging with AVDT_TRACE_WARNING. The patched region is fully present at android-security-14.0.0_r29.
- Android 15: Adapted fix: commit 0a4fd20189fa in android-security-15.0.0_r7, with the same logic but logging via log::warn. The patched region is fully present at android-security-15.0.0_r17.
- Android 16: Not affected (not listed by the bulletin). The patched region is present at android-security-16.0.0_r8.
- Android 17: Not affected (not listed by the bulletin). The patched region is present at android-security-17.0.0_r1.
Unknowns
- The exact downstream OOB access site, i.e. which parse function overruns p_proc_data, is not shown.
- Where and for which command p_ccb->p_proc_data is set up is not shown.
- Whether the Android 13 branch received the same commit, and what its avdt_msg_ind looks like. The bulletin lists 13 as affected, but the material has no 13 commit.
- Whether transaction label validation for RSP/REJ messages exists elsewhere.
- Whether any CMD parse path uses p_ccb->p_proc_data.