CVE-2025-22406 AI-generated analysis
platform/packages/modules/Bluetooth, system/stack (avct, bnep, hid, rfcomm, sdp)
At nine L2CAP send sites in eight Bluetooth stack files (AVCT, BNEP, HID device, RFCOMM, SDP), the log::warn on the failure path no longer reads the BT_HDR buffer after it has been passed to L2CA_DataWrite. The length is now saved in a local before the call or computed from pointers the code already has.
Root cause
At each patched site the code calls L2CA_DataWrite(cid, p_buf). When the call does not return L2CAP_DW_SUCCESS, it then logs p_buf->len (or hd_cb.pending_data->len, p->len, p_msg->len). The commit message says that in exceptional cases the buffer may already have been freed by the preceding call, so the log statement can read freed memory. The pattern was present in avct_lcb_msg_ind, bnep_congestion_ind, bnepu_check_send_packet, hidd_check_config_done, rfc_send_buf_uih, rfc_check_send_cmd, process_service_attr_rsp, process_service_search and process_service_attr_req.
How the fix works
- system/stack/avct/avct_lcb_act.cc:avct_lcb_msg_ind: adds `uint16_t len = p_buf->len;` before L2CA_DataWrite and logs `len` instead of `p_buf->len` when sending the AVCT_REJ fails.
- system/stack/bnep/bnep_main.cc:bnep_congestion_ind: in the loop that drains p_bcb->xmit_q once congestion clears, saves `len = p_buf->len` after the dequeue and before L2CA_DataWrite. The log uses `len`.
- system/stack/bnep/bnep_utils.cc:bnepu_check_send_packet: in the not-congested branch, saves `len` before L2CA_DataWrite. The log uses `len`.
- system/stack/hid/hidd_conn.cc:hidd_check_config_done: saves `len = hd_cb.pending_data->len` before L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data). The log uses `len`. The new line is mis-indented but sits inside the `if (hd_cb.pending_data)` block, so the logic is correct.
- system/stack/rfcomm/rfc_ts_frames.cc:rfc_send_buf_uih: for a non-MX DLCI, saves `len = p_buf->len` before L2CA_DataWrite. The log uses `len`.
- system/stack/rfcomm/rfc_utils.cc:rfc_check_send_cmd: in the loop that drains cmd_q, saves `len = p->len` after the dequeue and before L2CA_DataWrite. The log uses `len`.
- system/stack/sdp/sdp_discovery.cc:process_service_attr_rsp: the log now uses `p - p_start` (the same expression just assigned to p_msg->len) instead of `p_msg->len`.
- system/stack/sdp/sdp_server.cc:process_service_search and process_service_attr_req: the log now uses `p_rsp - p_rsp_start` (the value assigned to p_buf->len) instead of `p_buf->len`.
- L2CA_DataWrite itself is not changed. The fix only removes the reads of the buffer after the call at these sites.
Completeness
- The fix covers nine log statements in eight files. Each one now gets the length before the call or from local pointer arithmetic.
- The commit title 'Fix more memory-unsafe logging' suggests it follows earlier fixes of the same pattern. The material does not show whether other L2CA_DataWrite callers in the stack still log buffer fields after the call.
- L2CA_DataWrite is unchanged, so its handling of the buffer is too. Any call site that logs the buffer after the call would bring the pattern back.
Behavior changes
- No functional change. The warning now logs the length from before the call (saved in a local or computed from the same pointers) and no longer reads the buffer after L2CA_DataWrite.
Per major
- Android 14: Not affected per the bulletin. At android-security-14.0.0_r29 only 4/8 patched-region lines match, so the code at these sites differs from the Android 15 form. Whether the vulnerable log statements exist there is not shown.
- Android 15: Fixed by commit 806774b1cf64 in android-security-15.0.0_r5 (cherry-pick of internal change 43cfd234de9b). At android-security-15.0.0_r17, 7/8 lines are present. The r17 context shows the corrected log statements in the bnep, hid, rfcomm and sdp sites. The avct site is not shown in that context. Per index search, android-15.0.0_r36 has bnepu_check_send_packet with the `len` capture and a refactored stack::l2cap::get_interface().L2CA_DataWrite(...) != tL2CAP_DW_RESULT::SUCCESS call.
- Android 16: Not affected per the bulletin. 4/8 lines match at android-security-16.0.0_r8. Whether the fix is present there in refactored form is not shown.
- Android 17: Not affected per the bulletin. 4/8 lines match at android-security-17.0.0_r1. The form of the code there is not shown.
Unknowns
- Which site(s) the 'researcher POC' exercised, and the exact condition under which the buffer is freed before the log runs.
- Whether other L2CA_DataWrite callers in the stack still read buffer fields after the call (the commit follows earlier fixes that are not in the material).
- Whether the code in Android 14, 16 and 17 contains these log reads after the call, or the fix in another form.
- Why 1 of the 8 patched-region lines is missing at android-security-15.0.0_r17.