Commit message: None
CVE: CVE-2018-9505
CWE: CWE-125
Vulnerability description: In mca_ccb_hdl_req of mca_cact.cc, there is a possible out of bounds read due to a missing bounds check. This could lead to remote information disclosure over Bluetooth with no additional execution privileges needed. User interaction is not needed for exploitation. Product: Android Versions: Android-7.0 Android-7.1.1 Android-7.1.2 Android-8.0 Android-8.1 Android-9.0 Android ID: A-110791536

Project: Android

void mca_ccb_dl_open(tMCA_CCB* p_ccb, UNUSED_ATTR tMCA_CCB_EVT* p_data) {
  osi_free_and_reset((void**)&p_ccb->p_tx_req);
  osi_free_and_reset((void**)&p_ccb->p_rx_msg);
  p_ccb->status = MCA_CCB_STAT_NORM;
}

Project: Android

void mca_ccb_hdl_rsp(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data) {
  BT_HDR* p_pkt = &p_data->hdr;
 uint8_t* p;
  tMCA_CTRL evt_data;
 bool chk_mdl = false;
  tMCA_DCB* p_dcb;
  tMCA_RESULT result = MCA_BAD_HANDLE;
  tMCA_TC_TBL* p_tbl;

 if (p_ccb->p_tx_req) {
 /* verify that the received response matches the sent request */
    p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
    evt_data.hdr.op_code = *p++;
 if ((evt_data.hdr.op_code == 0) ||
 ((p_ccb->p_tx_req->op_code + 1) == evt_data.hdr.op_code)) {
      evt_data.rsp.rsp_code = *p++;
      mca_stop_timer(p_ccb);
      BE_STREAM_TO_UINT16(evt_data.hdr.mdl_id, p);
 if (evt_data.hdr.op_code == MCA_OP_MDL_CREATE_RSP) {
        evt_data.create_cfm.cfg = *p++;
        chk_mdl = true;
 } else if (evt_data.hdr.op_code == MCA_OP_MDL_RECONNECT_RSP)
        chk_mdl = true;

 if (chk_mdl) {
        p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
 if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS) {
 if (evt_data.hdr.mdl_id != p_dcb->mdl_id) {
            MCA_TRACE_ERROR("peer's mdl_id=%d != our mdl_id=%d",
                            evt_data.hdr.mdl_id, p_dcb->mdl_id);
 /* change the response code to be an error */
 if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS) {
              evt_data.rsp.rsp_code = MCA_RSP_BAD_MDL;
 /* send Abort */
              p_ccb->status = MCA_CCB_STAT_PENDING;
              MCA_Abort(mca_ccb_to_hdl(p_ccb));
 }
 } else if (p_dcb->p_chnl_cfg) {
 /* the data channel configuration is known. Proceed with data
             * channel initiation */
            BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_MCAP_DATA,
                                 p_ccb->sec_mask, p_ccb->data_vpsm,
                                 BTM_SEC_PROTO_MCA, p_ccb->p_tx_req->dcb_idx);
            p_dcb->lcid = mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm,
                                           p_dcb->p_chnl_cfg);
 if (p_dcb->lcid) {
              p_tbl = mca_tc_tbl_dalloc(p_dcb);
 if (p_tbl) {
                p_tbl->state = MCA_TC_ST_CONN;
                p_ccb->status = MCA_CCB_STAT_PENDING;
                result = MCA_SUCCESS;
 }
 }
 } else {
 /* mark this MCL as pending and wait for MCA_DataChnlCfg */
            p_ccb->status = MCA_CCB_STAT_PENDING;
            result = MCA_SUCCESS;
 }
 }

 if (result != MCA_SUCCESS && p_dcb) {
          mca_dcb_dealloc(p_dcb, NULL);
 }
 } /* end of chk_mdl */

 if (p_ccb->status != MCA_CCB_STAT_PENDING)
        osi_free_and_reset((void**)&p_ccb->p_tx_req);
      mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data);
 }
 /* else a bad response is received */
 } else {
 /* not expecting any response. drop it */
    MCA_TRACE_WARNING("dropping received rsp (not expecting a response)");
 }
  osi_free(p_data);
}

Project: Android

void mca_ccb_ll_open(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data) {
  tMCA_CTRL evt_data;
  p_ccb->cong = false;
  evt_data.connect_ind.mtu = p_data->open.peer_mtu;
  evt_data.connect_ind.bd_addr = p_ccb->peer_addr;
  mca_ccb_report_event(p_ccb, MCA_CONNECT_IND_EVT, &evt_data);
}

Project: Android

void mca_ccb_report_event(tMCA_CCB* p_ccb, uint8_t event, tMCA_CTRL* p_data) {
 if (p_ccb && p_ccb->p_rcb && p_ccb->p_rcb->p_cback)
 (*p_ccb->p_rcb->p_cback)(mca_rcb_to_handle(p_ccb->p_rcb),
                             mca_ccb_to_hdl(p_ccb), event, p_data);
}

Project: Android

void mca_ccb_rsp_tout(tMCA_CCB* p_ccb, UNUSED_ATTR tMCA_CCB_EVT* p_data) {
  tMCA_CTRL evt_data;

  mca_ccb_report_event(p_ccb, MCA_RSP_TOUT_IND_EVT, &evt_data);
}

Project: Android

void mca_ccb_snd_rsp(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data) {
  tMCA_CCB_MSG* p_msg = (tMCA_CCB_MSG*)p_data;
 uint8_t *p, *p_start;
  BT_HDR* p_pkt = (BT_HDR*)osi_malloc(MCA_CTRL_MTU + sizeof(BT_HDR));

  MCA_TRACE_DEBUG("%s cong=%d req=%d", __func__, p_ccb->cong, p_msg->op_code);
 /* assume that API functions verified the parameters */

  p_pkt->offset = L2CAP_MIN_OFFSET;
  p = p_start = (uint8_t*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
 *p++ = p_msg->op_code;
 *p++ = p_msg->rsp_code;
  UINT16_TO_BE_STREAM(p, p_msg->mdl_id);
 if (p_msg->rsp_code == MCA_RSP_SUCCESS) {
 if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP) {
 *p++ = p_msg->param;
 }
 if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP ||
        p_msg->op_code == MCA_OP_MDL_RECONNECT_RSP) {
      mca_dcb_by_hdl(p_msg->dcb_idx);
      BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_MCAP_DATA,
                           p_ccb->sec_mask, p_ccb->p_rcb->reg.data_psm,
                           BTM_SEC_PROTO_MCA, p_msg->dcb_idx);
      p_ccb->status = MCA_CCB_STAT_PENDING;
 /* set p_tx_req to block API_REQ/API_RSP before DL is up */
      osi_free_and_reset((void**)&p_ccb->p_tx_req);
      p_ccb->p_tx_req = p_ccb->p_rx_msg;
      p_ccb->p_rx_msg = NULL;
      p_ccb->p_tx_req->dcb_idx = p_msg->dcb_idx;
 }
 }

  osi_free_and_reset((void**)&p_ccb->p_rx_msg);
  p_pkt->len = p - p_start;
  L2CA_DataWrite(p_ccb->lcid, p_pkt);
}