fix(ble/bluedroid): Fix potential out-of-bounds issue

- add length check in hci_hal_h4_hdl_rx_packet to prevent OOB
- add adv data length check in btm_ble_cache_adv_data
- add indicate data length check in BTA_GATTS_HandleValueIndication
- add report length check in bta_hh_parse_keybd_rpt
- add report length check in BTA_HdSendReport
- add descriptor length check in BTA_HdRegisterApp
- prevent buffer overflow in attribute processing


(cherry picked from commit 71efec78c5)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
This commit is contained in:
Zhang Hai Peng
2025-11-27 20:09:12 +08:00
parent c260f37076
commit 64ccc92ab8
5 changed files with 54 additions and 5 deletions

View File

@@ -241,7 +241,7 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
if(p_buf->attr_val.attr_val != NULL){
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, len);
}
}
@@ -411,6 +411,14 @@ void BTA_GATTS_StopService(UINT16 service_id)
void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id, UINT16 data_len,
UINT8 *p_data, BOOLEAN need_confirm)
{
/* Validate data length against buffer size */
if (data_len > BTA_GATT_MAX_ATTR_LEN) {
APPL_TRACE_ERROR("GATT indication data too large: %u > %u",
data_len, BTA_GATT_MAX_ATTR_LEN);
return;
}
tBTA_GATTS_API_INDICATION *p_buf;
UINT16 len = sizeof(tBTA_GATTS_API_INDICATION);

View File

@@ -89,6 +89,20 @@ void BTA_HdDisable(void)
******************************************************************************/
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos)
{
/* Validate descriptor length before copying */
if (p_app_info->descriptor.dl_len > BTA_HD_APP_DESCRIPTOR_LEN) {
APPL_TRACE_ERROR("HID descriptor too large: %u > %u",
p_app_info->descriptor.dl_len, BTA_HD_APP_DESCRIPTOR_LEN);
return;
}
/* Validate descriptor data pointer */
if (p_app_info->descriptor.dl_len > 0 && p_app_info->descriptor.dsc_list == NULL) {
APPL_TRACE_ERROR("HID descriptor data NULL but length > 0: %u", p_app_info->descriptor.dl_len);
return;
}
tBTA_HD_REGISTER_APP *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_REGISTER_APP *)osi_malloc(sizeof(tBTA_HD_REGISTER_APP))) != NULL) {
@@ -158,6 +172,13 @@ extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report)
__func__, p_report->len, BTA_HD_REPORT_LEN);
return;
}
/* Validate report data pointer */
if (p_report->len > 0 && p_report->p_data == NULL) {
APPL_TRACE_ERROR("HID report data pointer NULL but length > 0: %d", p_report->len);
return;
}
if ((p_buf = (tBTA_HD_SEND_REPORT *)osi_malloc(sizeof(tBTA_HD_SEND_REPORT))) != NULL) {
p_buf->hdr.event = BTA_HD_API_SEND_REPORT_EVT;
p_buf->use_intr = p_report->use_intr;

View File

@@ -263,6 +263,18 @@ void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
UINT16 xx, yy, key_idx = 0;
UINT8 this_report[BTA_HH_MAX_RPT_CHARS];
/* Validate report length before processing */
if (report_len > BTA_HH_MAX_RPT_CHARS) {
APPL_TRACE_ERROR("HID report length exceeds maximum: %u > %u",
report_len, BTA_HH_MAX_RPT_CHARS);
return;
}
if (report_len == 0 || p_report == NULL) {
APPL_TRACE_ERROR("Invalid HID report data");
return;
}
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("bta_hh_parse_keybd_rpt: (report=%p, report_len=%d) called",
p_report, report_len);
@@ -463,7 +475,7 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
if (bta_hh_cb.p_cback) {
(*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status);
/* all connections are down, no waiting for diconnect */
/* all connections are down, no waiting for disconnect */
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
}
}

View File

@@ -508,9 +508,10 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
STREAM_TO_UINT8(length, stream);
}
if ((length + hdr_size) != packet->len) {
HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
"pkt_len=%d", type, hdr_size, length, packet->len);
// Prevents integer wrap-around when calculating (length + hdr_size).
if (length != (packet->len - hdr_size)) {
HCI_TRACE_ERROR("%s: SECURITY: parameter length (%d) exceeds packet bounds (%d)",
__func__, length, packet->len - hdr_size);
osi_free(packet);
return;
}

View File

@@ -3113,6 +3113,13 @@ void btm_ble_cache_adv_data(BD_ADDR bda, tBTM_INQ_RESULTS *p_cur, UINT8 data_len
p_cur->scan_rsp_len = 0;
}
/* Additional validation to prevent potential integer overflow */
if (data_len > BTM_BLE_CACHE_ADV_DATA_MAX) {
BTM_TRACE_ERROR("BLE advertising data length exceeds maximum: %u > %u",
data_len, BTM_BLE_CACHE_ADV_DATA_MAX);
return;
}
if (data_len > 0) {
p_cache = &p_le_inq_cb->adv_data_cache[p_le_inq_cb->adv_len];
if((data_len + p_le_inq_cb->adv_len) <= BTM_BLE_CACHE_ADV_DATA_MAX) {