mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'bugfix/fix_ble_security_issue_2025_v3_v5.4' into 'release/v5.4'
fix(ble/bluedroid): Fix type mismatch and length validation in HCI packet parser (v5.4) See merge request espressif/esp-idf!44666
This commit is contained in:
@@ -65,10 +65,15 @@ void osi_mutex_unlock(osi_mutex_t *mutex)
|
||||
xSemaphoreGive(*mutex);
|
||||
}
|
||||
|
||||
/** Delete a semaphore
|
||||
* @param mutex the mutex to delete */
|
||||
/** Delete a mutex
|
||||
* @param mutex the mutex to delete
|
||||
* Note: Safe to call with NULL or uninitialized mutex (IDFGH-16853)
|
||||
*/
|
||||
void osi_mutex_free(osi_mutex_t *mutex)
|
||||
{
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
return;
|
||||
}
|
||||
vSemaphoreDelete(*mutex);
|
||||
*mutex = NULL;
|
||||
}
|
||||
|
||||
@@ -69,9 +69,15 @@ osi_sem_take(osi_sem_t *sem, uint32_t timeout)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Deallocates a semaphore
|
||||
/** Deallocates a semaphore
|
||||
* @param sem the semaphore to delete
|
||||
* Note: Safe to call with NULL or uninitialized semaphore (IDFGH-16853)
|
||||
*/
|
||||
void osi_sem_free(osi_sem_t *sem)
|
||||
{
|
||||
if (sem == NULL || *sem == NULL) {
|
||||
return;
|
||||
}
|
||||
vSemaphoreDelete(*sem);
|
||||
*sem = NULL;
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ config BT_GATTC_MAX_CACHE_CHAR
|
||||
config BT_GATTC_NOTIF_REG_MAX
|
||||
int "Max gattc notify(indication) register number"
|
||||
depends on BT_GATTC_ENABLE
|
||||
range 1 64
|
||||
range 1 255
|
||||
default 5
|
||||
help
|
||||
Maximum GATTC notify(indication) register number
|
||||
@@ -1359,6 +1359,16 @@ config BT_BLE_FEAT_CREATE_SYNC_ENH
|
||||
help
|
||||
Enable the create sync enhancements
|
||||
|
||||
config BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
|
||||
int "Maximum retry count for periodic advertising create sync"
|
||||
depends on BT_BLE_50_EXTEND_SYNC_EN
|
||||
default 3
|
||||
range 0 16
|
||||
help
|
||||
Set the maximum retry count when periodic advertising create sync fails
|
||||
with error code 0x3E (Connection Failed to be Established).
|
||||
Set to 0 to disable retry. Default is 3.
|
||||
|
||||
menuconfig BT_BLE_FEAT_ISO_EN
|
||||
bool "Enable BLE 5.2 iso feature"
|
||||
depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_AUDIO_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -283,6 +283,27 @@ typedef uint8_t esp_gap_ble_channels[ESP_GAP_BLE_CHANNELS_LEN];
|
||||
|
||||
#define VENDOR_HCI_CMD_MASK (0x3F << 10) /**!< 0xFC00 */
|
||||
|
||||
/**
|
||||
* @brief BLE time interval conversion macros
|
||||
*
|
||||
* These macros convert time values in milliseconds to BLE interval units.
|
||||
*
|
||||
* - Advertising interval: unit is 0.625ms (range: 20ms to 10240ms)
|
||||
* - Connection interval: unit is 1.25ms (range: 7.5ms to 4000ms)
|
||||
* - Scan interval/window: unit is 0.625ms
|
||||
* - Periodic advertising interval: unit is 1.25ms
|
||||
* - Supervision timeout: unit is 10ms (range: 100ms to 32000ms)
|
||||
*
|
||||
* @note If the input value is not an exact multiple of the unit, the result will be rounded to the nearest value.
|
||||
* For example, ESP_BLE_GAP_ADV_ITVL_MS(25) = 40 (25ms / 0.625ms = 40), but ESP_BLE_GAP_ADV_ITVL_MS(25.5) = 40 (rounded).
|
||||
*/
|
||||
#define ESP_BLE_GAP_ADV_ITVL_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert advertising interval from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
|
||||
#define ESP_BLE_GAP_SCAN_ITVL_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert scan interval from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
|
||||
#define ESP_BLE_GAP_SCAN_WIN_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert scan window from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
|
||||
#define ESP_BLE_GAP_CONN_ITVL_MS(t) ((uint16_t)((t) * 1000 / 1250)) /*!< Convert connection interval from ms to 1.25ms units. If input is not a multiple of 1.25ms, it will be rounded to the nearest value. */
|
||||
#define ESP_BLE_GAP_PERIODIC_ADV_ITVL_MS(t) ((uint16_t)((t) * 1000 / 1250)) /*!< Convert periodic advertising interval from ms to 1.25ms units. If input is not a multiple of 1.25ms, it will be rounded to the nearest value. */
|
||||
#define ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((uint16_t)((t) / 10)) /*!< Convert supervision timeout from ms to 10ms units. If input is not a multiple of 10ms, it will be rounded to the nearest value. */
|
||||
|
||||
/* relate to BTM_BLE_AD_TYPE_xxx in stack/btm_ble_api.h */
|
||||
/// The type of advertising data(not adv_type)
|
||||
typedef enum {
|
||||
|
||||
@@ -528,6 +528,79 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
} else if (p_data->hdr.event == BTA_GATTC_API_SEARCH_EVT) {
|
||||
/*
|
||||
* Fix for Use-After-Free (UAF) bug in service search with filter_uuid.
|
||||
*
|
||||
* Problem Description:
|
||||
* ====================
|
||||
* In BTA_GATTC_ServiceSearchRequest(), memory is allocated as:
|
||||
* [tBTA_GATTC_API_SEARCH structure][tBT_UUID data]
|
||||
*
|
||||
* The p_srvc_uuid pointer points to the tBT_UUID data located right after
|
||||
* the structure:
|
||||
* p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1);
|
||||
*
|
||||
* When this command is enqueued (e.g., during DISCOVER_ST state), the original
|
||||
* code only performed a shallow copy:
|
||||
* - Only sizeof(tBTA_GATTC_DATA) was allocated for cmd_data
|
||||
* - memcpy copied the pointer VALUE (not the pointed data)
|
||||
* - After the original message is freed by bta_sys_event(), the p_srvc_uuid
|
||||
* pointer becomes a dangling pointer pointing to freed memory
|
||||
*
|
||||
* Memory layout before fix:
|
||||
*
|
||||
* Original (p_data): Copy (cmd_data):
|
||||
* +------------------+----------+ +------------------+
|
||||
* | API_SEARCH | tBT_UUID | | API_SEARCH |
|
||||
* | p_srvc_uuid: --------► | | p_srvc_uuid: --------► (dangling!)
|
||||
* +------------------+----------+ +------------------+
|
||||
* ↑
|
||||
* After free(), this memory may be
|
||||
* overwritten by other allocations
|
||||
*
|
||||
* Solution:
|
||||
* =========
|
||||
* For BTA_GATTC_API_SEARCH_EVT with non-NULL p_srvc_uuid, we need to:
|
||||
* 1. Allocate extra space for tBT_UUID
|
||||
* 2. Copy the structure
|
||||
* 3. Update p_srvc_uuid to point to the new location
|
||||
* 4. Copy the tBT_UUID data
|
||||
*
|
||||
* Memory layout after fix:
|
||||
*
|
||||
* Copy (cmd_data):
|
||||
* +------------------+----------+
|
||||
* | API_SEARCH | tBT_UUID |
|
||||
* | p_srvc_uuid: --------► | (points to its own copy)
|
||||
* +------------------+----------+
|
||||
*/
|
||||
if (p_data->api_search.p_srvc_uuid != NULL) {
|
||||
/* Allocate space for structure + UUID data (deep copy) */
|
||||
len = sizeof(tBTA_GATTC_DATA) + sizeof(tBT_UUID);
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(len)) != NULL) {
|
||||
memset(cmd_data, 0, len);
|
||||
/* Copy the structure */
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
/* Update pointer to point to the space after the structure */
|
||||
cmd_data->api_search.p_srvc_uuid = (tBT_UUID *)(cmd_data + 1);
|
||||
/* Copy the UUID data */
|
||||
memcpy(cmd_data->api_search.p_srvc_uuid,
|
||||
p_data->api_search.p_srvc_uuid, sizeof(tBT_UUID));
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
/* p_srvc_uuid is NULL, no extra space needed (search all services) */
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
|
||||
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
|
||||
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
|
||||
|
||||
@@ -247,6 +247,12 @@
|
||||
#define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
|
||||
#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
|
||||
#else
|
||||
#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX 3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_BLE_FEAT_ISO_EN
|
||||
#define UC_BT_BLE_FEAT_ISO_EN CONFIG_BT_BLE_FEAT_ISO_EN
|
||||
#else
|
||||
|
||||
@@ -296,6 +296,12 @@
|
||||
#define BLE_FEAT_CREATE_SYNC_ENH FALSE
|
||||
#endif
|
||||
|
||||
#ifdef UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
|
||||
#define BLE_FEAT_CREATE_SYNC_RETRY_MAX UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
|
||||
#else
|
||||
#define BLE_FEAT_CREATE_SYNC_RETRY_MAX 3
|
||||
#endif
|
||||
|
||||
#if (UC_BT_BLE_FEAT_ISO_EN == TRUE)
|
||||
#define BLE_FEAT_ISO_EN TRUE
|
||||
#else
|
||||
|
||||
@@ -87,7 +87,7 @@ typedef struct {
|
||||
uint16_t ble_ext_adv_data_max_len;
|
||||
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
|
||||
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
uint16_t get_ble_periodic_advertiser_list_size;
|
||||
uint8_t get_ble_periodic_advertiser_list_size;
|
||||
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
} controller_local_param_t;
|
||||
|
||||
@@ -219,7 +219,7 @@ static void parse_ble_read_suggested_default_data_length_response(
|
||||
uint16_t *ble_default_packet_txtime_ptr)
|
||||
{
|
||||
|
||||
uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
|
||||
uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 4 /* bytes after: 2+2 */);
|
||||
if (stream) {
|
||||
STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream);
|
||||
STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream);
|
||||
@@ -235,7 +235,7 @@ static void parse_ble_read_adv_max_len_response(
|
||||
uint16_t *adv_max_len_ptr)
|
||||
{
|
||||
|
||||
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */);
|
||||
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 2 /* bytes after */);
|
||||
if (stream) {
|
||||
// Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length
|
||||
STREAM_TO_UINT16(*adv_max_len_ptr, stream);
|
||||
@@ -246,7 +246,7 @@ static void parse_ble_read_adv_max_len_response(
|
||||
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
static void parse_ble_read_periodic_adv_list_size_response(
|
||||
BT_HDR *response,
|
||||
uint16_t *periodic_adv_list_size_ptr)
|
||||
uint8_t *periodic_adv_list_size_ptr)
|
||||
{
|
||||
|
||||
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_PERIOD_ADV_LIST_SIZE, 1 /* bytes after */);
|
||||
|
||||
@@ -114,7 +114,7 @@ typedef struct {
|
||||
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
void (*parse_ble_read_periodic_adv_list_size_response) (
|
||||
BT_HDR *response,
|
||||
uint16_t *periodic_advertiser_list_size
|
||||
uint8_t *periodic_advertiser_list_size
|
||||
);
|
||||
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
@@ -39,6 +39,19 @@ typedef struct {
|
||||
tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0};
|
||||
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
|
||||
|
||||
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
/* Create sync retry control block */
|
||||
typedef struct {
|
||||
bool in_use; /* Whether sync creation is in progress */
|
||||
uint8_t retry_count; /* Current retry count */
|
||||
tBTM_BLE_Periodic_Sync_Params params; /* Saved sync parameters for retry */
|
||||
} tBTM_BLE_SYNC_RETRY_CB;
|
||||
|
||||
static tBTM_BLE_SYNC_RETRY_CB sync_retry_cb = {0};
|
||||
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
|
||||
|
||||
extern void btm_ble_inter_set(bool extble_inter);
|
||||
|
||||
#if !UC_BT_STACK_NO_LOG
|
||||
@@ -880,11 +893,19 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params)
|
||||
SET_BIT(option, 2);
|
||||
}
|
||||
#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
|
||||
|
||||
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
/* Save parameters for potential retry */
|
||||
memcpy(&sync_retry_cb.params, params, sizeof(tBTM_BLE_Periodic_Sync_Params));
|
||||
sync_retry_cb.retry_count = 0;
|
||||
sync_retry_cb.in_use = true;
|
||||
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type,
|
||||
params->addr, params->sync_timeout, params->sync_cte_type)) {
|
||||
BTM_TRACE_ERROR("LE PA CreateSync cmd failed");
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
sync_retry_cb.in_use = false;
|
||||
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
}
|
||||
|
||||
end:
|
||||
@@ -942,6 +963,11 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void)
|
||||
tBTM_STATUS status = BTM_SUCCESS;
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
/* Clear retry state when sync is cancelled */
|
||||
sync_retry_cb.in_use = false;
|
||||
sync_retry_cb.retry_count = 0;
|
||||
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err);
|
||||
status = BTM_HCI_ERROR | err;
|
||||
@@ -1399,6 +1425,48 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par
|
||||
return;
|
||||
}
|
||||
|
||||
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
/* Check if retry is needed for error 0x3E (Connection Failed to be Established) */
|
||||
if (params->status == HCI_ERR_CONN_FAILED_ESTABLISHMENT &&
|
||||
sync_retry_cb.in_use &&
|
||||
sync_retry_cb.retry_count < BLE_FEAT_CREATE_SYNC_RETRY_MAX) {
|
||||
|
||||
sync_retry_cb.retry_count++;
|
||||
BTM_TRACE_WARNING("%s, Create sync failed with 0x3E, retry %d/%d",
|
||||
__func__, sync_retry_cb.retry_count, BLE_FEAT_CREATE_SYNC_RETRY_MAX);
|
||||
|
||||
/* Build option from saved parameters */
|
||||
uint8_t option = 0x00;
|
||||
if (sync_retry_cb.params.filter_policy) {
|
||||
SET_BIT(option, 0);
|
||||
}
|
||||
#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
|
||||
if (sync_retry_cb.params.reports_disabled) {
|
||||
SET_BIT(option, 1);
|
||||
}
|
||||
if (sync_retry_cb.params.filter_duplicates) {
|
||||
SET_BIT(option, 2);
|
||||
}
|
||||
#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
|
||||
|
||||
/* Retry create sync with saved parameters */
|
||||
if (btsnd_hcic_ble_periodic_adv_create_sync(option,
|
||||
sync_retry_cb.params.sid,
|
||||
sync_retry_cb.params.addr_type,
|
||||
sync_retry_cb.params.addr,
|
||||
sync_retry_cb.params.sync_timeout,
|
||||
sync_retry_cb.params.sync_cte_type)) {
|
||||
/* Retry command sent successfully, wait for next event */
|
||||
return;
|
||||
}
|
||||
/* If retry command failed, fall through to report failure */
|
||||
BTM_TRACE_ERROR("%s, Retry create sync command failed", __func__);
|
||||
}
|
||||
|
||||
/* Clear retry state */
|
||||
sync_retry_cb.in_use = false;
|
||||
sync_retry_cb.retry_count = 0;
|
||||
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
|
||||
memcpy(&cb_params.sync_estab, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
|
||||
@@ -554,7 +554,13 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
|
||||
tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
|
||||
|
||||
UNUSED(op_code);
|
||||
UNUSED(len);
|
||||
|
||||
/* Fix: Validate minimum length (opcode:1 + handle:2 + reason:1 = 4 bytes) */
|
||||
if (len < 4) {
|
||||
GATT_TRACE_ERROR("invalid error rsp len: %d", len);
|
||||
gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG("%s", __func__);
|
||||
STREAM_TO_UINT8(opcode, p);
|
||||
@@ -800,6 +806,14 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
|
||||
handle_len = 4;
|
||||
}
|
||||
|
||||
/* Check value_len is sufficient before subtraction to prevent underflow */
|
||||
if (value_len < handle_len) {
|
||||
GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: value_len(%d) < handle_len(%d), invalid response",
|
||||
value_len, handle_len);
|
||||
gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
value_len -= handle_len; /* subtract the handle pairs bytes */
|
||||
len -= 1;
|
||||
|
||||
|
||||
@@ -479,7 +479,13 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
UNUSED(len);
|
||||
|
||||
/* Fix: Validate minimum length (flags: 1 byte) */
|
||||
if (len < 1) {
|
||||
GATT_TRACE_ERROR("invalid exec write req len: %d", len);
|
||||
gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
|
||||
@@ -1234,10 +1240,13 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
|
||||
switch (op_code) {
|
||||
case GATT_SIGN_CMD_WRITE:
|
||||
if (op_code == GATT_SIGN_CMD_WRITE) {
|
||||
GATT_TRACE_DEBUG("Write CMD with data signing" );
|
||||
len -= GATT_AUTH_SIGN_LEN;
|
||||
/* Fix: Validate length before subtraction to prevent underflow */
|
||||
if (len < GATT_AUTH_SIGN_LEN) {
|
||||
GATT_TRACE_ERROR("signed write len too short: %d", len);
|
||||
return; /* GATT_SIGN_CMD_WRITE has no response */
|
||||
}
|
||||
GATT_TRACE_DEBUG("Write CMD with data signing" );
|
||||
len -= GATT_AUTH_SIGN_LEN;
|
||||
/* fall through */
|
||||
case GATT_CMD_WRITE:
|
||||
case GATT_REQ_WRITE:
|
||||
@@ -1473,7 +1482,13 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
|
||||
UINT8 sec_flag, key_size, *p;
|
||||
UINT16 offset = 0, value_len = 0;
|
||||
|
||||
UNUSED (len);
|
||||
/* Fix: Validate length for GATT_REQ_READ_BLOB (needs offset: 2 bytes) */
|
||||
if (op_code == GATT_REQ_READ_BLOB && len < 2) {
|
||||
GATT_TRACE_ERROR("invalid read blob req len: %d", len);
|
||||
gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_msg = (BT_HDR *)osi_calloc(buf_len)) == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");
|
||||
|
||||
|
||||
@@ -715,6 +715,11 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
UINT16 cmd_len;
|
||||
UINT16 min_interval, max_interval, latency, timeout;
|
||||
|
||||
if (pkt_len < L2CAP_CMD_OVERHEAD) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - pkt too short: %d", pkt_len);
|
||||
return;
|
||||
}
|
||||
|
||||
p_pkt_end = p + pkt_len;
|
||||
|
||||
STREAM_TO_UINT8 (cmd_code, p);
|
||||
@@ -731,6 +736,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
case L2CAP_CMD_REJECT:
|
||||
case L2CAP_CMD_ECHO_RSP:
|
||||
case L2CAP_CMD_INFO_RSP:
|
||||
if (cmd_len < 2) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
|
||||
return;
|
||||
}
|
||||
p += 2;
|
||||
break;
|
||||
case L2CAP_CMD_ECHO_REQ:
|
||||
@@ -739,6 +748,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CMD_BLE_UPDATE_REQ:
|
||||
if (cmd_len < 8) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
|
||||
return;
|
||||
}
|
||||
STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
|
||||
STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
|
||||
STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */
|
||||
@@ -781,6 +794,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CMD_BLE_UPDATE_RSP: {
|
||||
if (cmd_len < 2) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
|
||||
return;
|
||||
}
|
||||
UINT16 result = 0;
|
||||
STREAM_TO_UINT16(result, p); //result = 0 connection param accepted, result = 1 connection param rejected.
|
||||
UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE;
|
||||
@@ -793,6 +810,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
}
|
||||
case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: {
|
||||
if (cmd_len < 10) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
|
||||
return;
|
||||
}
|
||||
tL2C_CCB *p_ccb = NULL;
|
||||
tL2C_RCB *p_rcb = NULL;
|
||||
UINT16 spsm;
|
||||
@@ -841,6 +862,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
}
|
||||
case L2CAP_CMD_DISC_REQ: {
|
||||
if (cmd_len < 4) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
|
||||
return;
|
||||
}
|
||||
tL2C_CCB *p_ccb = NULL;
|
||||
UINT16 lcid;
|
||||
UINT16 rcid;
|
||||
|
||||
Reference in New Issue
Block a user