Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2f7b647 authored by Ugo Yu's avatar Ugo Yu
Browse files

DO NOT MERGE: Fix possible OOB when AVDT data channel recive ACL data

Bug: 111450156

Change-Id: Id23eeedcb7bde5866cd53a2f7f1c30f27c5352f6
Merged-In: Id23eeedcb7bde5866cd53a2f7f1c30f27c5352f6
(cherry picked from commit b0125caafec2183d73fc899ce5a8aee43a6e54af)
parent 88268c3a
Loading
Loading
Loading
Loading
+56 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
 *
 ******************************************************************************/

#include <cutils/log.h>
#include <string.h>
#include "a2dp_codec_api.h"
#include "avdt_api.h"
@@ -233,10 +234,14 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB* 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);
@@ -244,18 +249,19 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB* 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 */
@@ -283,6 +289,12 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB* 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);
}

#if (AVDT_REPORTING == TRUE)
@@ -300,6 +312,7 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* 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, *p_rpt;

@@ -307,6 +320,14 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* p_scb, uint8_t* p, uint16_t len) {
  if (p_scb->cs.p_report_cback) {
    p_rpt = &report;
    /* 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;
@@ -314,6 +335,14 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* 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);
@@ -322,6 +351,14 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* 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;
@@ -333,8 +370,23 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* p_scb, uint8_t* p, uint16_t len) {

      case AVDT_RTCP_PT_SDES: /* the packet type - SDES (Source Description) */
        if (*p == AVDT_RTCP_SDES_CNAME) {
          min_len += sizeof(tAVDT_REPORT_DATA) + 2;
          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;
          }
          p_rpt = (tAVDT_REPORT_DATA*)(p + 2);
        } 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 + 2);
            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;
@@ -349,6 +401,7 @@ uint8_t* avdt_scb_hdl_report(tAVDT_SCB* p_scb, uint8_t* p, uint16_t len) {
    if (result == AVDT_SUCCESS)
      (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, p_rpt);
  }
avdt_scb_hdl_report_exit:
  p_start += len;
  return p_start;
}