From baa9bf5bfe4a6f3e52ac927aaf4463f37f81294e Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 30 Oct 2018 00:47:04 +0800 Subject: [PATCH] Fix possible OOB when AVDT data channel recive ACL data Bug: 111450156 Change-Id: Id23eeedcb7bde5866cd53a2f7f1c30f27c5352f6 --- stack/avdt/avdt_scb_act.cc | 67 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/stack/avdt/avdt_scb_act.cc b/stack/avdt/avdt_scb_act.cc index d55a22e70..9ff926509 100644 --- a/stack/avdt/avdt_scb_act.cc +++ b/stack/avdt/avdt_scb_act.cc @@ -23,6 +23,7 @@ * ******************************************************************************/ +#include #include #include "a2dp_codec_api.h" #include "avdt_api.h" @@ -230,10 +231,14 @@ void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) { uint16_t offset; uint16_t ex_len; uint8_t pad_len = 0; + uint16_t len = p_data->p_pkt->len; p = p_start = (uint8_t*)(p_data->p_pkt + 1) + p_data->p_pkt->offset; /* parse media packet header */ + offset = 12; + // AVDT_MSG_PRS_OCTET1(1) + AVDT_MSG_PRS_M_PT(1) + UINT16(2) + UINT32(4) + 4 + if (offset > len) goto length_error; AVDT_MSG_PRS_OCTET1(p, o_v, o_p, o_x, o_cc); AVDT_MSG_PRS_M_PT(p, m_pt, marker); BE_STREAM_TO_UINT16(seq, p); @@ -241,18 +246,19 @@ void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) { p += 4; /* skip over any csrc's in packet */ + offset += o_cc * 4; p += o_cc * 4; /* check for and skip over extension header */ if (o_x) { + offset += 4; + if (offset > len) goto length_error; p += 2; BE_STREAM_TO_UINT16(ex_len, p); + offset += ex_len * 4; p += ex_len * 4; } - /* save our new offset */ - offset = (uint16_t)(p - p_start); - /* adjust length for any padding at end of packet */ if (o_p) { /* padding length in last byte of packet */ @@ -280,6 +286,12 @@ void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) { osi_free_and_reset((void**)&p_data->p_pkt); } } + return; +length_error: + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING("%s: hdl packet length %d too short: must be at least %d", + __func__, len, offset); + osi_free_and_reset((void**)&p_data->p_pkt); } /******************************************************************************* @@ -296,12 +308,21 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { uint8_t* p_start = p; uint32_t ssrc; uint8_t o_v, o_p, o_cc; + uint16_t min_len = 0; AVDT_REPORT_TYPE pt; tAVDT_REPORT_DATA report; AVDT_TRACE_DEBUG("%s", __func__); if (p_scb->stream_config.p_report_cback) { /* parse report packet header */ + min_len += 8; + if (min_len > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", __func__, + 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; @@ -309,6 +330,14 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { switch (pt) { case AVDT_RTCP_PT_SR: /* the packet type - SR (Sender Report) */ + min_len += 20; + if (min_len > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", + __func__, 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); @@ -317,6 +346,14 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { break; case AVDT_RTCP_PT_RR: /* the packet type - RR (Receiver Report) */ + min_len += 20; + if (min_len > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", + __func__, 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; @@ -328,9 +365,25 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { case AVDT_RTCP_PT_SDES: /* the packet type - SDES (Source Description) */ uint8_t sdes_type; + min_len += 1; + if (min_len > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", + __func__, len, min_len); + goto avdt_scb_hdl_report_exit; + } BE_STREAM_TO_UINT8(sdes_type, p); if (sdes_type == AVDT_RTCP_SDES_CNAME) { uint8_t name_length; + min_len += 1; + if (min_len > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", + __func__, len, min_len); + goto avdt_scb_hdl_report_exit; + } BE_STREAM_TO_UINT8(name_length, p); if (name_length > len - 2 || name_length > AVDT_MAX_CNAME_SIZE) { result = AVDT_BAD_PARAMS; @@ -338,6 +391,13 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { BE_STREAM_TO_ARRAY(p, &(report.cname[0]), name_length); } } else { + if (min_len + 1 > len) { + android_errorWriteLog(0x534e4554, "111450156"); + AVDT_TRACE_WARNING( + "%s: hdl packet length %d too short: must be at least %d", + __func__, len, min_len); + goto avdt_scb_hdl_report_exit; + } AVDT_TRACE_WARNING(" - SDES SSRC=0x%08x sc=%d %d len=%d %s", ssrc, o_cc, *p, *(p + 1), p + 2); result = AVDT_BUSY; @@ -353,6 +413,7 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { (*p_scb->stream_config.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, &report); } +avdt_scb_hdl_report_exit: p_start += len; return p_start; } -- 2.11.0