From 4e47e201771bcb4faa001395a4f8e6d9a969398d Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Sat, 11 Oct 2025 16:31:43 +0800 Subject: [PATCH] fix(bt/bluedroid): fixed potential OOB read in the reporting handler Thanks to Luigino Camastra and Pavel Kohout from Aisle Research as co-reporters for discovering and reporting this issue. --- .../host/bluedroid/stack/avdt/avdt_scb_act.c | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c b/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c index baf489df5e6..5fae98eed8a 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c @@ -351,13 +351,18 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) UINT8 *p_start = p; UINT32 ssrc; UINT8 o_v, o_p, o_cc; + UINT32 min_len = 0; AVDT_REPORT_TYPE pt; - tAVDT_REPORT_DATA report, *p_rpt; + tAVDT_REPORT_DATA report; AVDT_TRACE_DEBUG( "avdt_scb_hdl_report"); if (p_scb->cs.p_report_cback) { - p_rpt = &report; /* parse report packet header */ + min_len += 8; + if (len < min_len) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } AVDT_MSG_PRS_RPT_OCTET1(p, o_v, o_p, o_cc); pt = *p++; p += 2; @@ -370,6 +375,11 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) switch (pt) { case AVDT_RTCP_PT_SR: /* the packet type - SR (Sender Report) */ + min_len += 20; + if (len < min_len) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } BE_STREAM_TO_UINT32(report.sr.ntp_sec, p); BE_STREAM_TO_UINT32(report.sr.ntp_frac, p); BE_STREAM_TO_UINT32(report.sr.rtp_time, p); @@ -378,6 +388,11 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) break; case AVDT_RTCP_PT_RR: /* the packet type - RR (Receiver Report) */ + min_len += 20; + if (len < min_len) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } report.rr.frag_lost = *p; BE_STREAM_TO_UINT32(report.rr.packet_lost, p); report.rr.packet_lost &= 0xFFFFFF; @@ -388,11 +403,32 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) break; case AVDT_RTCP_PT_SDES: /* the packet type - SDES (Source Description) */ - if (*p == AVDT_RTCP_SDES_CNAME) { - p_rpt = (tAVDT_REPORT_DATA *)(p + 2); + min_len += 1; + if (len < min_len) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } + uint8_t sdes_type; + BE_STREAM_TO_UINT8(sdes_type, p); + if (sdes_type == AVDT_RTCP_SDES_CNAME) { + min_len += 1; + if (len < min_len) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } + uint8_t name_length; + BE_STREAM_TO_UINT8(name_length, p);\ + if ((name_length > len - min_len) || (name_length > AVDT_MAX_CNAME_SIZE)) { + result = AVDT_BAD_PARAMS; + } else { + BE_STREAM_TO_ARRAY(p, &(report.cname[0]), name_length); + } } else { - AVDT_TRACE_WARNING( " - SDES SSRC=0x%08x sc=%d %d len=%d %s\n", - ssrc, o_cc, *p, *(p + 1), p + 2); + if (len < min_len + 1) { + AVDT_TRACE_WARNING("hdl packet length %u too short: must be at least %u", len, min_len); + goto avdt_scb_hdl_report_exit; + } + AVDT_TRACE_WARNING( " - SDES SSRC=0x%08x sc=%d %d len=%d\n", ssrc, o_cc, sdes_type, *p); result = AVDT_BUSY; } break; @@ -403,10 +439,12 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) } if (result == AVDT_SUCCESS) { - (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, p_rpt); + (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, &report); } } + +avdt_scb_hdl_report_exit: p_start += len; return p_start; }