From 47c41de0b2c6dcc6872d8b849206186721bc758a Mon Sep 17 00:00:00 2001 From: yangfeng Date: Mon, 11 Aug 2025 17:54:32 +0800 Subject: [PATCH] fix(bt/bluedroid): Prevent out-of-bounds access and add type check when resolving EIR data --- .../bt/host/bluedroid/api/esp_gap_bt_api.c | 22 ++++++++++- .../api/include/api/esp_gap_bt_api.h | 2 +- .../bt/host/bluedroid/stack/btm/btm_inq.c | 37 ++++++++++++++++--- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_gap_bt_api.c b/components/bt/host/bluedroid/api/esp_gap_bt_api.c index 86619430b9..cc874374e8 100644 --- a/components/bt/host/bluedroid/api/esp_gap_bt_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_bt_api.c @@ -138,7 +138,27 @@ uint8_t *esp_bt_gap_resolve_eir_data(uint8_t *eir, esp_bt_eir_type_t type, uint8 return NULL; } - return BTM_CheckEirData(eir, type, length); + switch (type) { + case ESP_BT_EIR_TYPE_FLAGS: + case ESP_BT_EIR_TYPE_INCMPL_16BITS_UUID: + case ESP_BT_EIR_TYPE_CMPL_16BITS_UUID: + case ESP_BT_EIR_TYPE_INCMPL_32BITS_UUID: + case ESP_BT_EIR_TYPE_CMPL_32BITS_UUID: + case ESP_BT_EIR_TYPE_INCMPL_128BITS_UUID: + case ESP_BT_EIR_TYPE_CMPL_128BITS_UUID: + case ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME: + case ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME: + case ESP_BT_EIR_TYPE_TX_POWER_LEVEL: + case ESP_BT_EIR_TYPE_URL: + case ESP_BT_EIR_TYPE_MANU_SPECIFIC: { + return BTM_CheckEirData(eir, type, length); + } + default: + /*Error type*/ + break; + } + + return NULL; } esp_err_t esp_bt_gap_config_eir_data(esp_bt_eir_data_t *eir_data) diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h index 1c05ffc58e..07866b8a3c 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h @@ -88,7 +88,7 @@ typedef struct { #define ESP_BT_EIR_TYPE_TX_POWER_LEVEL 0x0a /*!< Tx power level, value is 1 octet ranging from -127 to 127, unit is dBm*/ #define ESP_BT_EIR_TYPE_URL 0x24 /*!< Uniform resource identifier */ #define ESP_BT_EIR_TYPE_MANU_SPECIFIC 0xff /*!< Manufacturer specific data */ -#define ESP_BT_EIR_TYPE_MAX_NUM 12 /*!< MAX number of EIR type */ +#define ESP_BT_EIR_TYPE_MAX_NUM 12 /*!< MAX number of EIR type */ typedef uint8_t esp_bt_eir_type_t; diff --git a/components/bt/host/bluedroid/stack/btm/btm_inq.c b/components/bt/host/bluedroid/stack/btm/btm_inq.c index 528c7a066f..ed84167982 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/components/bt/host/bluedroid/stack/btm/btm_inq.c @@ -2420,24 +2420,51 @@ tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff, BOOLEAN fec_required) UINT8 *BTM_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length ) { UINT8 *p = p_eir; + UINT8 *p_data_length = p_length; UINT8 length; UINT8 eir_type; BTM_TRACE_API("BTM_CheckEirData type=0x%02X\n", type); + if (!p_length) { + if ((p_data_length = (UINT8 *)osi_malloc(sizeof(UINT8))) == NULL) { + BTM_TRACE_ERROR("%s: Memory allocation failed.", __func__); + return NULL; + } + } + STREAM_TO_UINT8(length, p); - while ( length && (p - p_eir <= HCI_EXT_INQ_RESPONSE_LEN)) { + while ( length ) { STREAM_TO_UINT8(eir_type, p); if ( eir_type == type ) { + if ((p + length - 1) > (p_eir + HCI_EXT_INQ_RESPONSE_LEN)) { + /*avoid memory overflow*/ + *p_data_length = 0; + p = NULL; + goto exit; + } /* length doesn't include itself */ - *p_length = length - 1; /* minus the length of type */ - return p; + *p_data_length = length - 1; /* minus the length of type */ + goto exit; } p += length - 1; /* skip the length of data */ + + /* Break loop if eir data is in an incorrect format, + as it may lead to memory overflow */ + if ( p >= p_eir + HCI_EXT_INQ_RESPONSE_LEN ) { + break; + } + STREAM_TO_UINT8(length, p); } - *p_length = 0; - return NULL; + *p_data_length = 0; + p = NULL; + +exit: + if (!p_length) { + osi_free(p_data_length); + } + return p; } /*******************************************************************************