【蓝牙】CVE-2018-9360 process_l2cap_cmd_L2CAP_CMD_CONN_REQ未判断缓冲区边界造成信息泄露

补丁

  • https://android.googlesource.com/platform/system/bt/+/b66fc16410ff96e9119f8eb282e67960e79075c8

/*******************************************************************************
 *
 * Function         process_l2cap_cmd
 *
 * Description      This function is called when a packet is received on the
 *                  L2CAP signalling CID
 *
 * Returns          void
 *
 ******************************************************************************/
static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
    ...
    /* An L2CAP packet may contain multiple commands */
    while (true) {
        /* Smallest command is 4 bytes */
        p = p_next_cmd; // p此时作为指针在缓冲区游动
        if (p > (p_pkt_end - 4)) break; // 保证剩余缓冲区至少还有4字节的数据剩余
    
        ...
        switch (cmd_code) {
            ...
            case L2CAP_CMD_CONN_REQ:
                // 取了4字节,取值前未判断:p + 2 > p_pkt_end
                STREAM_TO_UINT16(con_info.psm, p);
                STREAM_TO_UINT16(rcid, p);
                p_rcb = l2cu_find_rcb_by_psm(con_info.psm);
                if (p_rcb == NULL) {
                    L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: %d", con_info.psm);
                    l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_PSM);
                    break;
                } else {
                    if (!p_rcb->api.pL2CA_ConnectInd_Cb) {
                        L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for outgoing-only connection PSM: %d", con_info.psm);
                        l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_PSM);
                        break;
                    }
                }
                p_ccb = l2cu_allocate_ccb(p_lcb, 0);
                if (p_ccb == NULL) {
                    L2CAP_TRACE_ERROR("L2CAP - unable to allocate CCB");
                    l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_RESOURCES);
                    break;
                }
                p_ccb->remote_id = id;
                p_ccb->p_rcb = p_rcb;
                p_ccb->remote_cid = rcid;

                l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
                break;
        
                ...
        }
    }
}

l2cu_find_rcb_by_psm(con_info.psm)找不到的时候,就会返回NULL,会调用l2cu_reject_connection(),这个函数描述可以仔细看看,不存在PSM的时候就会调用,并且通过l2c_link_check_send_pkts()发送数据包回去

PoC

Last updated