2023.09.19

CVE-2022-20447 A-233604485 ID High 13

patch

分析

BNEP_WriteBuf -> bnepu_check_send_packet中,是有场景可能导致p_buf被释放的,但是在从PAN_WriteBuf开始的调用链里,并没有对其做这种情况做检验。最后在[5]处的pcb->write.octets += p_buf->len可能导致UAF。
patch是把UAF的Use给消除掉,即在调用BNEP_WriteBuf之前,先把p_buf->len给拿出来赋值给局部变量len,那么后面给pcb->write.octets赋值的时候使用局部变量就不会产生UAF了。
诶,那么搜一下BNEP_WriteBuf,看看调用它的地方还有没有类似的问题,可惜的是就两处,并没有类似的问题。

  • PAN_WriteBuf
// system/stack/pan/pan_api.cc
/*******************************************************************************
 *
 * Function         PAN_WriteBuf
 *
 * Description      This sends data over the PAN connections. If this is called
 *                  on GN or NAP side and the packet is multicast or broadcast
 *                  it will be sent on all the links. Otherwise the correct link
 *                  is found based on the destination address and forwarded on
 *                  it. If the return value is not PAN_SUCCESS, the application
 *                  should take care of releasing the message buffer.
 *
 * Parameters:      handle   - handle for the connection
 *                  dst      - MAC or BD Addr of the destination device
 *                  src      - MAC or BD Addr of the source who sent this packet
 *                  protocol - protocol of the ethernet packet like IP or ARP
 *                  p_buf    - pointer to the data buffer
 *                  ext      - to indicate that extension headers present
 *
 * Returns          PAN_SUCCESS       - if the data is sent successfully
 *                  PAN_FAILURE       - if the connection is not found or
 *                                           there is an error in sending data
 *
 ******************************************************************************/
tPAN_RESULT PAN_WriteBuf(uint16_t handle, const RawAddress& dst,
                         const RawAddress& src, uint16_t protocol,
                         BT_HDR* p_buf, bool ext) {
  ......
  // [1] 调用BNEP_WriteBuf,传入p_buf
  result = BNEP_WriteBuf(pcb->handle, dst, p_buf, protocol, &src, ext); 
  if (result == BNEP_IGNORE_CMD) {
    PAN_TRACE_DEBUG("PAN ignored data buf write to PANU");
    pcb->write.errors++;
    return PAN_IGNORE_CMD;
  } else if (result != BNEP_SUCCESS) {
    PAN_TRACE_ERROR("PAN failed to send data buf to the PANU");
    pcb->write.errors++;
    return (tPAN_RESULT)result;
  }
  pcb->write.octets += p_buf->len; // [5] 在BNEP_WriteBuf中,p_buf可能已经释放了,这里仍然使用,可能造成UAF
  pcb->write.packets++;
  PAN_TRACE_DEBUG("PAN successfully sent data buf to the PANU");
  return PAN_SUCCESS;
}


  • BNEP_WriteBuf
// system/stack/bnep/bnep_api.cc
tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, const RawAddress& p_dest_addr,
                           BT_HDR* p_buf, uint16_t protocol,
                           const RawAddress* p_src_addr, bool fw_ext_present) {
    ......
  /* Send the data or queue it up */
  bnepu_check_send_packet(p_bcb, p_buf); // [2] 调用bnepu_check_send_packet,传入p_buf
  return (BNEP_SUCCESS); // [4] 没有对bnepu_check_send_packet中释放p_buf的情况做检查,直接返回BNEP_SUCCESS
}
  • bnepu_check_send_packet
// system/stack/bnep/bnep_utils.cc
/*******************************************************************************
 *
 * Function         bnepu_check_send_packet
 *
 * Description      This function tries to send a packet to L2CAP.
 *                  If L2CAP is flow controlled, it enqueues the
 *                  packet to the transmit queue
 *
 * Returns          void
 *
 ******************************************************************************/
void bnepu_check_send_packet(tBNEP_CONN* p_bcb, BT_HDR* p_buf) {
  LOG_DEBUG("BNEP - bnepu_check_send_packet for CID: 0x%x", p_bcb->l2cap_cid);
  if (p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED) {
    if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH) {
      LOG_WARN("BNEP - congested, dropping buf, CID: 0x%x", p_bcb->l2cap_cid);
      osi_free(p_buf); // [3] 满足上述条件时,会释放p_buf
    } else {
      fixed_queue_enqueue(p_bcb->xmit_q, p_buf);
    }
  } else {
    L2CA_DataWrite(p_bcb->l2cap_cid, p_buf);
  }
}