diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index c5c2e1a428..ad0d8d3059 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -100,7 +100,7 @@ static void btu_hcif_hardware_error_evt (UINT8 *p); static void btu_hcif_flush_occured_evt (void); static void btu_hcif_role_change_evt (UINT8 *p); #endif // #if (CLASSIC_BT_INCLUDED == TRUE) -static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p); +static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p, UINT8 evt_len); #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_mode_change_evt (UINT8 *p); @@ -194,14 +194,14 @@ static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p); #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) void btu_ble_create_big_cmd_status(UINT8 status); -static void btu_ble_big_create_complete_evt(UINT8 *p); +static void btu_ble_big_create_complete_evt(UINT8 *p, UINT8 evt_len); void btu_ble_big_terminate_cmd_status(UINT8 status); static void btu_ble_big_terminate_complete_evt(UINT8 *p); #endif // #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) static void btu_ble_create_big_sync_cmd_status(UINT8 status); -static void btu_ble_big_sync_establish_evt(UINT8 *p); +static void btu_ble_big_sync_establish_evt(UINT8 *p, UINT8 evt_len); static void btu_ble_big_sync_lost_evt(UINT8 *p); static void btu_ble_biginfo_adv_report_evt(UINT8 *p); #endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) @@ -222,10 +222,10 @@ static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason); #if (BLE_FEAT_CTE_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) -static void btu_ble_cte_connless_iq_report_evt(UINT8 *p); +static void btu_ble_cte_connless_iq_report_evt(UINT8 *p, UINT8 evt_len); #endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) -static void btu_ble_cte_conn_iq_report_evt(UINT8 *p); +static void btu_ble_cte_conn_iq_report_evt(UINT8 *p, UINT8 evt_len); static void btu_ble_cte_req_failed_evt(UINT8 *p); #endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) #endif // #if (BLE_FEAT_CTE_EN == TRUE) @@ -241,7 +241,7 @@ static void btu_ble_subrate_change_evt(UINT8 *p); #if (BT_BLE_FEAT_PAWR_EN == TRUE) static void btu_ble_pa_subevt_data_request_evt(UINT8 *p); -static void btu_ble_pa_response_report_evt(UINT8 *p); +static void btu_ble_pa_response_report_evt(UINT8 *p, UINT8 evt_len); #endif // (BT_BLE_FEAT_PAWR_EN == TRUE) #if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) @@ -250,8 +250,8 @@ static void btu_ble_cs_read_remote_fae_tab_evt(UINT8 *p); static void btu_ble_cs_security_enable_cmpl_evt(UINT8 *p); static void btu_ble_cs_config_cmpl_evt(UINT8 *p); static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p); -static void btu_ble_cs_subevt_result_evt(UINT8 *p); -static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p); +static void btu_ble_cs_subevt_result_evt(UINT8 *p, UINT8 evt_len); +static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p, UINT8 evt_len); #endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) #if (BLE_42_ADV_EN == TRUE) @@ -287,9 +287,20 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #if BLE_INCLUDED == TRUE UINT8 ble_sub_code; #endif + if (p_msg->len < 2) { + HCI_TRACE_ERROR("%s: HCI event too short (len=%u), dropping", __func__, p_msg->len); + return; + } + STREAM_TO_UINT8 (hci_evt_code, p); STREAM_TO_UINT8 (hci_evt_len, p); + if (hci_evt_len > p_msg->len - 2) { + HCI_TRACE_ERROR("%s: HCI evt 0x%02x param len %u exceeds buffer (avail=%u), dropping", + __func__, hci_evt_code, hci_evt_len, p_msg->len - 2); + return; + } + switch (hci_evt_code) { #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_INQUIRY_COMP_EVT: @@ -372,7 +383,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) break; #endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_NUM_COMPL_DATA_PKTS_EVT: - btu_hcif_num_compl_data_pkts_evt (p); + btu_hcif_num_compl_data_pkts_evt (p, hci_evt_len); break; #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_MODE_CHANGE_EVT: @@ -469,6 +480,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #if (BLE_INCLUDED == TRUE) case HCI_BLE_EVENT: + if (hci_evt_len < 1) { + HCI_TRACE_ERROR("%s: BLE meta event param len %u invalid (need >= 1), dropping", __func__, hci_evt_len); + break; + } STREAM_TO_UINT8 (ble_sub_code, p); hci_evt_len--; HCI_TRACE_DEBUG("BLE HCI(id=%d) event = 0x%02x)", hci_evt_code, ble_sub_code); @@ -572,7 +587,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) case HCI_BLE_BIG_CREATE_COMPLETE_EVT: - btu_ble_big_create_complete_evt(p); + btu_ble_big_create_complete_evt(p, hci_evt_len); break; case HCI_BLE_BIG_TERMINATE_COMPLETE_EVT: btu_ble_big_terminate_complete_evt(p); @@ -580,7 +595,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #endif // #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) case HCI_BLE_BIG_SYNC_ESTABLISHED_EVT: - btu_ble_big_sync_establish_evt(p); + btu_ble_big_sync_establish_evt(p, hci_evt_len); break; case HCI_BLE_BIG_SYNC_LOST_EVT: btu_ble_big_sync_lost_evt(p); @@ -593,13 +608,13 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #if (BLE_FEAT_CTE_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) case HCI_BLE_CONNLESS_IQ_REPORT_EVT: - btu_ble_cte_connless_iq_report_evt(p); + btu_ble_cte_connless_iq_report_evt(p, hci_evt_len); break; #endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) case HCI_BLE_CONN_IQ_REPORT_EVT: - btu_ble_cte_conn_iq_report_evt(p); + btu_ble_cte_conn_iq_report_evt(p, hci_evt_len); break; case HCI_BLE_CTE_REQUEST_FAILED_EVT: btu_ble_cte_req_failed_evt(p); @@ -625,7 +640,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_ble_pa_subevt_data_request_evt(p); break; case HCI_BLE_PA_RESPONSE_REPORT_EVT: - btu_ble_pa_response_report_evt(p); + btu_ble_pa_response_report_evt(p, hci_evt_len); break; #endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) #if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) @@ -645,10 +660,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_ble_cs_proc_enable_cmpl_evt(p); break; case HCI_BLE_CS_SUBEVENT_RESULT_EVT: - btu_ble_cs_subevt_result_evt(p); + btu_ble_cs_subevt_result_evt(p, hci_evt_len); break; case HCI_BLE_CS_SUBEVENT_RESULT_CONTINUE_EVT: - btu_ble_cs_subevt_result_continue_evt(p); + btu_ble_cs_subevt_result_continue_evt(p, hci_evt_len); break; #endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) } @@ -1400,7 +1415,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) case HCI_BLE_BIG_TERMINATE_SYNC: - UINT16 big_handle; + UINT8 big_handle; STREAM_TO_UINT8(status, p); STREAM_TO_UINT8(big_handle, p); btm_ble_big_sync_terminate_complete(status, big_handle); @@ -1925,14 +1940,14 @@ static void btu_hcif_role_change_evt (UINT8 *p) ** Returns void ** *******************************************************************************/ -static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p) +static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p, UINT8 evt_len) { /* Process for L2CAP and SCO */ - l2c_link_process_num_completed_pkts (p); + l2c_link_process_num_completed_pkts (p, evt_len); /* Send on to SCO */ #if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE) - btm_sco_process_num_completed_pkts (p); + btm_sco_process_num_completed_pkts (p, evt_len); #endif } #if (CLASSIC_BT_INCLUDED == TRUE) @@ -2553,19 +2568,36 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) UINT16 evt_type = 0; uint8_t addr_type; BD_ADDR bda; + UINT16 remaining; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); return; } + if (evt_len < 1) { + HCI_TRACE_ERROR("%s, evt_len too short (%u)", __func__, evt_len); + return; + } + STREAM_TO_UINT8(num_reports, p); + remaining = evt_len - 1; if (num_reports == 0) { HCI_TRACE_ERROR("%s, Invalid number reports is 0", __func__); } + /* Per-report fixed fields: evt_type(2) + addr_type(1) + bda(6) + + * primary_phy(1) + secondary_phy(1) + sid(1) + tx_power(1) + rssi(1) + + * per_adv_interval(2) + dir_addr_type(1) + dir_addr(6) + adv_data_len(1) = 24 */ + #define EXT_ADV_RPT_FIXED_LEN 24 + while (num_reports--) { + if (remaining < EXT_ADV_RPT_FIXED_LEN) { + HCI_TRACE_ERROR("%s, remaining %u too short for report (need %u)", + __func__, remaining, EXT_ADV_RPT_FIXED_LEN); + return; + } #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) /* Save current report start position for address resolution callback */ pp = p; @@ -2613,6 +2645,14 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) STREAM_TO_UINT8(ext_adv_report.dir_addr_type, p); STREAM_TO_BDADDR(ext_adv_report.dir_addr, p); STREAM_TO_UINT8(ext_adv_report.adv_data_len, p); + remaining -= EXT_ADV_RPT_FIXED_LEN; + + if (ext_adv_report.adv_data_len > remaining) { + HCI_TRACE_ERROR("%s, adv_data_len %u exceeds remaining %u", + __func__, ext_adv_report.adv_data_len, remaining); + return; + } + if (ext_adv_report.adv_data_len) { ext_adv_report.adv_data = p; } else { @@ -2621,6 +2661,7 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) btm_ble_ext_adv_report_evt(&ext_adv_report); p += ext_adv_report.adv_data_len; + remaining -= ext_adv_report.adv_data_len; } } @@ -2937,7 +2978,7 @@ void btu_ble_create_big_cmd_status(UINT8 status) } } -static void btu_ble_big_create_complete_evt(UINT8 *p) +static void btu_ble_big_create_complete_evt(UINT8 *p, UINT8 evt_len) { HCI_TRACE_DEBUG("%s", __func__); tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0}; @@ -2948,6 +2989,15 @@ static void btu_ble_big_create_complete_evt(UINT8 *p) return; } + /* Fixed fields: status(1) + big_handle(1) + big_sync_delay(3) + * + transport_latency(3) + phy(1) + nse(1) + bn(1) + pto(1) + irc(1) + * + max_pdu(2) + iso_interval(2) + num_bis(1) = 18 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 18) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=18)", __func__, evt_len); + return; + } + STREAM_TO_UINT8(big_cmpl.status, p); STREAM_TO_UINT8(big_cmpl.big_handle, p); STREAM_TO_UINT24(big_cmpl.big_sync_delay, p); @@ -2961,11 +3011,14 @@ static void btu_ble_big_create_complete_evt(UINT8 *p) STREAM_TO_UINT16(big_cmpl.iso_interval, p); STREAM_TO_UINT8(num_bis, p); - // Validate num_bis to prevent buffer overflow if (num_bis > BLE_ISO_BIS_MAX_COUNT) { HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); num_bis = BLE_ISO_BIS_MAX_COUNT; } + if (num_bis > (evt_len - 18) / 2) { + HCI_TRACE_ERROR("%s, num_bis %d exceeds evt_len %u, truncating", __func__, num_bis, evt_len); + num_bis = (evt_len - 18) / 2; + } big_cmpl.num_bis = num_bis; for (uint8_t i = 0; i < num_bis; i++) @@ -3014,7 +3067,7 @@ void btu_ble_create_big_sync_cmd_status(UINT8 status) } } -static void btu_ble_big_sync_establish_evt(UINT8 *p) +static void btu_ble_big_sync_establish_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_BIG_SYNC_ESTAB_CMPL big_estb = {0}; UINT8 num_bis; @@ -3024,6 +3077,15 @@ static void btu_ble_big_sync_establish_evt(UINT8 *p) return; } + /* Fixed fields: status(1) + big_handle(1) + transport_latency_big(3) + * + nse(1) + bn(1) + pto(1) + irc(1) + max_pdu(2) + iso_interval(2) + * + num_bis(1) = 14 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 14) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=14)", __func__, evt_len); + return; + } + STREAM_TO_UINT8(big_estb.status, p); STREAM_TO_UINT8(big_estb.big_handle, p); STREAM_TO_UINT24(big_estb.transport_latency_big, p); @@ -3035,11 +3097,14 @@ static void btu_ble_big_sync_establish_evt(UINT8 *p) STREAM_TO_UINT16(big_estb.iso_interval, p); STREAM_TO_UINT8(num_bis, p); - // Validate num_bis to prevent buffer overflow if (num_bis > BLE_ISO_BIS_MAX_COUNT) { HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); num_bis = BLE_ISO_BIS_MAX_COUNT; } + if (num_bis > (evt_len - 14) / 2) { + HCI_TRACE_ERROR("%s, num_bis %d exceeds evt_len %u, truncating", __func__, num_bis, evt_len); + num_bis = (evt_len - 14) / 2; + } big_estb.num_bis = num_bis; for (uint8_t i = 0; i < num_bis; i++) @@ -3095,7 +3160,7 @@ static void btu_ble_biginfo_adv_report_evt(UINT8 *p) #if (BLE_FEAT_CTE_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) -static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) +static void btu_ble_cte_connless_iq_report_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT connless_iq_rpt = {0}; UINT8 sample_count; @@ -3105,6 +3170,15 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) return; } + /* Fixed fields: sync_handle(2) + channel_idx(1) + rssi(2) + * + rssi_ant_id(1) + cte_type(1) + slot_dur(1) + pkt_status(1) + * + periodic_evt_counter(2) + sample_count(1) = 12 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 12) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=12)", __func__, evt_len); + return; + } + STREAM_TO_UINT16(connless_iq_rpt.sync_handle, p); STREAM_TO_UINT8(connless_iq_rpt.channel_idx, p); STREAM_TO_UINT16(connless_iq_rpt.rssi, p); @@ -3115,11 +3189,14 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) STREAM_TO_UINT16(connless_iq_rpt.periodic_evt_counter, p); STREAM_TO_UINT8(sample_count, p); - // Validate sample_count to prevent buffer overflow if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) { HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT); sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT; } + if (sample_count > (evt_len - 12) / 2) { + HCI_TRACE_ERROR("%s, sample_count %d exceeds evt_len %u, truncating", __func__, sample_count, evt_len); + sample_count = (evt_len - 12) / 2; + } connless_iq_rpt.sample_count = sample_count; for (uint8_t i = 0; i < sample_count; i++) @@ -3137,7 +3214,7 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) #endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) -static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) +static void btu_ble_cte_conn_iq_report_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_CTE_CONN_IQ_REPORT_EVT conn_iq_rpt = {0}; UINT8 sample_count; @@ -3147,6 +3224,15 @@ static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) return; } + /* Fixed fields: conn_handle(2) + rx_phy(1) + data_channel_idx(1) + * + rssi(2) + rssi_ant_id(1) + cte_type(1) + slot_dur(1) + pkt_status(1) + * + conn_evt_counter(2) + sample_count(1) = 13 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 13) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=13)", __func__, evt_len); + return; + } + STREAM_TO_UINT16(conn_iq_rpt.conn_handle, p); STREAM_TO_UINT8(conn_iq_rpt.rx_phy, p); STREAM_TO_UINT8(conn_iq_rpt.data_channel_idx, p); @@ -3158,11 +3244,14 @@ static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) STREAM_TO_UINT16(conn_iq_rpt.conn_evt_counter, p); STREAM_TO_UINT8(sample_count, p); - // Validate sample_count to prevent buffer overflow if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) { HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT); sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT; } + if (sample_count > (evt_len - 13) / 2) { + HCI_TRACE_ERROR("%s, sample_count %d exceeds evt_len %u, truncating", __func__, sample_count, evt_len); + sample_count = (evt_len - 13) / 2; + } conn_iq_rpt.sample_count = sample_count; for (uint8_t i = 0; i < sample_count; i++) @@ -3268,7 +3357,7 @@ static void btu_ble_pa_subevt_data_request_evt(UINT8 *p) btm_ble_pa_subevt_data_req_evt(&pa_subevt_req_evt); } -static void btu_ble_pa_response_report_evt(UINT8 *p) +static void btu_ble_pa_response_report_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_PA_RSP_REPORT_EVT pa_rsp_rpt_evt = {0}; if (!p) { @@ -3276,33 +3365,58 @@ static void btu_ble_pa_response_report_evt(UINT8 *p) return; } + /* Fixed fields: adv_handle(1) + subevt(1) + tx_status(1) + num_rsp(1) = 4 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 4) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=4)", __func__, evt_len); + return; + } + STREAM_TO_UINT8(pa_rsp_rpt_evt.adv_handle, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.subevt, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.tx_status, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.num_rsp, p); - // num_rsp is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + UINT8 remaining = evt_len - 4; + if (pa_rsp_rpt_evt.num_rsp) { pa_rsp_rpt_evt.rsp_data_info = osi_malloc(pa_rsp_rpt_evt.num_rsp * sizeof(tBTM_BLE_PA_RSP_DATA_INFO)); if (pa_rsp_rpt_evt.rsp_data_info) { for (UINT8 i = 0; i < pa_rsp_rpt_evt.num_rsp; i++) { + /* Per-response fixed: tx_power(1)+rssi(1)+cte_type(1)+rsp_slot(1)+data_status(1)+data_len(1) = 6 */ + if (remaining < 6) { + HCI_TRACE_ERROR("%s, remaining %u too short for response %d", __func__, remaining, i); + pa_rsp_rpt_evt.num_rsp = i; + break; + } STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].tx_power, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rssi, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].cte_type, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rsp_slot, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_status, p); STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_len, p); - // data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + remaining -= 6; + if (pa_rsp_rpt_evt.rsp_data_info[i].data_len > remaining) { + HCI_TRACE_ERROR("%s, data_len %d exceeds remaining %u at index %d", + __func__, pa_rsp_rpt_evt.rsp_data_info[i].data_len, remaining, i); + pa_rsp_rpt_evt.rsp_data_info[i].data_len = 0; + pa_rsp_rpt_evt.rsp_data_info[i].data = NULL; + pa_rsp_rpt_evt.num_rsp = i + 1; + break; + } if (pa_rsp_rpt_evt.rsp_data_info[i].data_len) { pa_rsp_rpt_evt.rsp_data_info[i].data = osi_malloc(pa_rsp_rpt_evt.rsp_data_info[i].data_len); if (pa_rsp_rpt_evt.rsp_data_info[i].data) { STREAM_TO_ARRAY(pa_rsp_rpt_evt.rsp_data_info[i].data, p, pa_rsp_rpt_evt.rsp_data_info[i].data_len); } else { HCI_TRACE_ERROR("%s, no enough memory for data_len %d at index %d", __func__, pa_rsp_rpt_evt.rsp_data_info[i].data_len, i); + p += pa_rsp_rpt_evt.rsp_data_info[i].data_len; + remaining -= pa_rsp_rpt_evt.rsp_data_info[i].data_len; pa_rsp_rpt_evt.rsp_data_info[i].data_len = 0; } + remaining -= pa_rsp_rpt_evt.rsp_data_info[i].data_len; } else { pa_rsp_rpt_evt.rsp_data_info[i].data = NULL; } @@ -3451,13 +3565,25 @@ static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p) btm_ble_cs_proc_enable_cmpl_evt(&proc_en); } -static void btu_ble_cs_subevt_result_evt(UINT8 *p) +static void btu_ble_cs_subevt_result_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT subevt_result = {0}; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); return; } + + /* Fixed fields: conn_handle(2) + config_id(1) + + * start_acl_conn_event_counter(2) + procedure_counter(2) + + * frequency_compensation(2) + reference_power_level(1) + + * procedure_done_status(1) + subevent_done_status(1) + abort_reason(1) + + * num_ant_paths(1) + num_steps_reported(1) = 15 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 15) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=15)", __func__, evt_len); + return; + } + STREAM_TO_UINT16(subevt_result.conn_handle, p); STREAM_TO_UINT8(subevt_result.config_id, p); STREAM_TO_UINT16(subevt_result.start_acl_conn_event_counter, p); @@ -3471,27 +3597,49 @@ static void btu_ble_cs_subevt_result_evt(UINT8 *p) UINT8 num_steps_reported; STREAM_TO_UINT8(num_steps_reported, p); - // Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160) if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) { HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED); num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED; } subevt_result.num_steps_reported = num_steps_reported; - subevt_result.step_info = osi_malloc(subevt_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)); - if (subevt_result.step_info) { + UINT8 remaining = evt_len - 15; + subevt_result.step_info = (subevt_result.num_steps_reported > 0) + ? osi_malloc(subevt_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)) + : NULL; + if (subevt_result.step_info || subevt_result.num_steps_reported == 0) { for (uint8_t i = 0; i < subevt_result.num_steps_reported; i++) { + /* Per-step fixed: step_mode(1) + step_channel(1) + step_data_len(1) = 3 */ + if (remaining < 3) { + HCI_TRACE_ERROR("%s, remaining %u too short for step %d", __func__, remaining, i); + subevt_result.num_steps_reported = i; + break; + } STREAM_TO_UINT8(subevt_result.step_info[i].step_mode, p); STREAM_TO_UINT8(subevt_result.step_info[i].step_channel, p); STREAM_TO_UINT8(subevt_result.step_info[i].step_data_len, p); - // step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + remaining -= 3; + if (subevt_result.step_info[i].step_data_len > remaining) { + HCI_TRACE_ERROR("%s, step_data_len %d exceeds remaining %u at step %d", + __func__, subevt_result.step_info[i].step_data_len, remaining, i); + subevt_result.step_info[i].step_data_len = 0; + subevt_result.step_info[i].data = NULL; + subevt_result.num_steps_reported = i + 1; + break; + } subevt_result.step_info[i].data = osi_malloc(subevt_result.step_info[i].step_data_len); if (subevt_result.step_info[i].data) { STREAM_TO_ARRAY(subevt_result.step_info[i].data, p, subevt_result.step_info[i].step_data_len); } else if (subevt_result.step_info[i].step_data_len) { HCI_TRACE_ERROR("%s, no memory.", __func__); + p += subevt_result.step_info[i].step_data_len; + subevt_result.step_info[i].step_data_len = 0; + subevt_result.step_info[i].data = NULL; + subevt_result.num_steps_reported = i + 1; + break; } + remaining -= subevt_result.step_info[i].step_data_len; } } @@ -3510,7 +3658,7 @@ static void btu_ble_cs_subevt_result_evt(UINT8 *p) } -static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p) +static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p, UINT8 evt_len) { tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT subevt_continue_result = {0}; @@ -3519,6 +3667,15 @@ static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p) return; } + /* Fixed fields: conn_handle(2) + config_id(1) + proc_done_status(1) + * + subevt_done_status(1) + abort_reason(1) + num_ant_paths(1) + * + num_steps_reported(1) = 8 bytes + * (subevent_code already subtracted from evt_len by caller) */ + if (evt_len < 8) { + HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=8)", __func__, evt_len); + return; + } + STREAM_TO_UINT16(subevt_continue_result.conn_handle, p); STREAM_TO_UINT8(subevt_continue_result.config_id, p); STREAM_TO_UINT8(subevt_continue_result.proc_done_status, p); @@ -3528,26 +3685,47 @@ static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p) UINT8 num_steps_reported; STREAM_TO_UINT8(num_steps_reported, p); - // Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160) if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) { HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED); num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED; } subevt_continue_result.num_steps_reported = num_steps_reported; - subevt_continue_result.step_info = osi_malloc(subevt_continue_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)); - if (subevt_continue_result.step_info) { + UINT8 remaining = evt_len - 8; + subevt_continue_result.step_info = (subevt_continue_result.num_steps_reported > 0) + ? osi_malloc(subevt_continue_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)) + : NULL; + if (subevt_continue_result.step_info || subevt_continue_result.num_steps_reported == 0) { for (uint8_t i = 0; i < subevt_continue_result.num_steps_reported; i++) { + if (remaining < 3) { + HCI_TRACE_ERROR("%s, remaining %u too short for step %d", __func__, remaining, i); + subevt_continue_result.num_steps_reported = i; + break; + } STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_mode, p); STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_channel, p); STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_data_len, p); - // step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + remaining -= 3; + if (subevt_continue_result.step_info[i].step_data_len > remaining) { + HCI_TRACE_ERROR("%s, step_data_len %d exceeds remaining %u at step %d", + __func__, subevt_continue_result.step_info[i].step_data_len, remaining, i); + subevt_continue_result.step_info[i].step_data_len = 0; + subevt_continue_result.step_info[i].data = NULL; + subevt_continue_result.num_steps_reported = i + 1; + break; + } subevt_continue_result.step_info[i].data = osi_malloc(subevt_continue_result.step_info[i].step_data_len); if (subevt_continue_result.step_info[i].data) { STREAM_TO_ARRAY(subevt_continue_result.step_info[i].data, p, subevt_continue_result.step_info[i].step_data_len); } else if (subevt_continue_result.step_info[i].step_data_len) { HCI_TRACE_ERROR("%s, no memory.", __func__); + p += subevt_continue_result.step_info[i].step_data_len; + subevt_continue_result.step_info[i].step_data_len = 0; + subevt_continue_result.step_info[i].data = NULL; + subevt_continue_result.num_steps_reported = i + 1; + break; } + remaining -= subevt_continue_result.step_info[i].step_data_len; } } else { HCI_TRACE_ERROR("%s, no memory for step_info.", __func__); diff --git a/components/bt/host/bluedroid/stack/btu/btu_task.c b/components/bt/host/bluedroid/stack/btu/btu_task.c index 23fbd72af7..2fe59a9260 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_task.c +++ b/components/bt/host/bluedroid/stack/btu/btu_task.c @@ -449,7 +449,17 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) osi_mutex_lock(&btu_general_alarm_lock, OSI_MUTEX_MAX_TIMEOUT); if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) { alarm = osi_alarm_new("btu_gen", btu_general_alarm_cb, (void *)p_tle, 0); - hash_map_set(btu_general_alarm_hash_map, p_tle, alarm); + if (alarm == NULL) { + HCI_TRACE_ERROR("%s Unable to create new alarm", __func__); + osi_mutex_unlock(&btu_general_alarm_lock); + return; + } + if (!hash_map_set(btu_general_alarm_hash_map, p_tle, alarm)) { + HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__); + osi_alarm_free(alarm); + osi_mutex_unlock(&btu_general_alarm_lock); + return; + } } osi_mutex_unlock(&btu_general_alarm_lock); @@ -569,8 +579,12 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti osi_mutex_unlock(&btu_l2cap_alarm_lock); return; } - - hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm); + if (!hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm)) { + HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__); + osi_alarm_free(alarm); + osi_mutex_unlock(&btu_l2cap_alarm_lock); + return; + } } osi_mutex_unlock(&btu_l2cap_alarm_lock); @@ -656,7 +670,17 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ osi_mutex_lock(&btu_oneshot_alarm_lock, OSI_MUTEX_MAX_TIMEOUT); if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) { alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0); - hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm); + if (alarm == NULL) { + HCI_TRACE_ERROR("%s Unable to create new alarm", __func__); + osi_mutex_unlock(&btu_oneshot_alarm_lock); + return; + } + if (!hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm)) { + HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__); + osi_alarm_free(alarm); + osi_mutex_unlock(&btu_oneshot_alarm_lock); + return; + } } osi_mutex_unlock(&btu_oneshot_alarm_lock);