From 029ed39579f9ae3cea1dc65d9ff735aea0aec8e7 Mon Sep 17 00:00:00 2001 From: "zhiweijian@espressif.com" Date: Wed, 6 Jul 2022 15:56:05 +0800 Subject: [PATCH] Fixed bluedroid host memory overflow --- .../bt/host/bluedroid/api/esp_gattc_api.c | 49 +++++++++++++++++++ .../bt/host/bluedroid/api/esp_gatts_api.c | 17 ++++++- .../host/bluedroid/stack/gatt/att_protocol.c | 6 +++ .../bt/host/bluedroid/stack/gatt/gatt_api.c | 39 +++++++++++++++ .../bt/host/bluedroid/stack/gatt/gatt_utils.c | 20 ++++++++ .../bluedroid/stack/gatt/include/gatt_int.h | 2 + .../bt/host/bluedroid/stack/l2cap/l2c_api.c | 7 +++ 7 files changed, 138 insertions(+), 2 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_gattc_api.c b/components/bt/host/bluedroid/api/esp_gattc_api.c index 5edac5f33f..f64dca7d8f 100644 --- a/components/bt/host/bluedroid/api/esp_gattc_api.c +++ b/components/bt/host/bluedroid/api/esp_gattc_api.c @@ -13,6 +13,7 @@ #include "btc_gatt_util.h" #include "stack/l2cdefs.h" #include "stack/l2c_api.h" +#include "gatt_int.h" #if (GATTC_INCLUDED == TRUE) @@ -327,6 +328,12 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -358,6 +365,12 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, return ESP_GATT_ILLEGAL_PARAMETER; } + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -384,6 +397,12 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -415,6 +434,12 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -442,6 +467,12 @@ esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -474,6 +505,12 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -506,6 +543,12 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -536,6 +579,12 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; diff --git a/components/bt/host/bluedroid/api/esp_gatts_api.c b/components/bt/host/bluedroid/api/esp_gatts_api.c index c620a7f8e7..ef82e87be6 100644 --- a/components/bt/host/bluedroid/api/esp_gatts_api.c +++ b/components/bt/host/bluedroid/api/esp_gatts_api.c @@ -14,6 +14,7 @@ #include "common/bt_target.h" #include "stack/l2cdefs.h" #include "stack/l2c_api.h" +#include "gatt_int.h" #if (GATTS_INCLUDED == TRUE) #define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type)) @@ -251,7 +252,13 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, btc_ble_gatts_args_t arg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - + + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; @@ -279,7 +286,13 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, btc_ble_gatts_args_t arg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - + + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + LOG_WARN("%s, The connection not created.", __func__); + return ESP_ERR_INVALID_STATE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_SEND_RESPONSE; diff --git a/components/bt/host/bluedroid/stack/gatt/att_protocol.c b/components/bt/host/bluedroid/stack/gatt/att_protocol.c index 15ca89f915..52ac13da1e 100644 --- a/components/bt/host/bluedroid/stack/gatt/att_protocol.c +++ b/components/bt/host/bluedroid/stack/gatt/att_protocol.c @@ -312,6 +312,12 @@ BT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle, p_buf->len += 2; } + if(payload_size < GATT_DEF_BLE_MTU_SIZE || payload_size > GATT_MAX_MTU_SIZE) { + GATT_TRACE_ERROR("invalid payload_size %d", payload_size); + osi_free(p_buf); + return NULL; + } + if (len > 0 && p_data != NULL) { /* ensure data not exceed MTU size */ if (payload_size - p_buf->len < len) { diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_api.c b/components/bt/host/bluedroid/stack/gatt/gatt_api.c index ad1e7da5cc..d556aac26b 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_api.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_api.c @@ -583,6 +583,11 @@ tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, U return (tGATT_STATUS) GATT_INVALID_CONN_ID; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_WRONG_STATE; + } + if (! GATT_HANDLE_IS_VALID (attr_handle)) { return GATT_ILLEGAL_PARAMETER; } @@ -650,6 +655,11 @@ tGATT_STATUS GATTS_HandleValueNotification (UINT16 conn_id, UINT16 attr_handle, return (tGATT_STATUS) GATT_INVALID_CONN_ID; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_WRONG_STATE; + } + if (GATT_HANDLE_IS_VALID (attr_handle)) { notif.handle = attr_handle; notif.len = val_len; @@ -697,6 +707,11 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, return (tGATT_STATUS) GATT_INVALID_CONN_ID; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_WRONG_STATE; + } + if (p_tcb->sr_cmd.trans_id != trans_id) { GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n", conn_id, p_tcb->sr_cmd.op_code); @@ -818,6 +833,11 @@ tGATT_STATUS GATTC_ConfigureMTU (UINT16 conn_id) return GATT_ILLEGAL_PARAMETER; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_ERROR; + } + /* Validate that the link is BLE, not BR/EDR */ if (p_tcb->transport != BT_TRANSPORT_LE) { return GATT_ERROR; @@ -870,6 +890,10 @@ tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type, return GATT_ILLEGAL_PARAMETER; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_ERROR; + } if (gatt_is_clcb_allocated(conn_id)) { GATT_TRACE_ERROR("GATTC_Discover GATT_BUSY conn_id = %d", conn_id); @@ -932,6 +956,11 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM return GATT_ILLEGAL_PARAMETER; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_ERROR; + } + if (gatt_is_clcb_allocated(conn_id)) { GATT_TRACE_ERROR("GATTC_Read GATT_BUSY conn_id = %d", conn_id); return GATT_BUSY; @@ -1010,6 +1039,11 @@ tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_ return GATT_ILLEGAL_PARAMETER; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_ERROR; + } + if (gatt_is_clcb_allocated(conn_id)) { GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id); return GATT_BUSY; @@ -1076,6 +1110,11 @@ tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute) return GATT_ILLEGAL_PARAMETER; } + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + GATT_TRACE_ERROR("connection not established\n"); + return GATT_ERROR; + } + if (gatt_is_clcb_allocated(conn_id)) { GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id); return GATT_BUSY; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c index f64c302385..83e0d1cfbb 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c @@ -896,6 +896,26 @@ BOOLEAN gatt_is_bda_connected(BD_ADDR bda) return connected; } +/******************************************************************************* +** +** Function gatt_check_connection_state_by_tcb +** +** Description +** +** Returns TRUE if connected. Otherwise connection not established. +** +*******************************************************************************/ +BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb) +{ + BOOLEAN connected = FALSE; + + if(p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) { + connected = TRUE; + } + + return connected; +} + /******************************************************************************* ** ** Function gatt_find_i_tcb_by_addr diff --git a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h index eaebe7c401..a96b661001 100644 --- a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -751,6 +751,8 @@ extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_lo extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary); extern tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db); +extern BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb); + extern void gatt_reset_bgdev_list(void); extern uint16_t gatt_get_local_mtu(void); extern void gatt_set_local_mtu(uint16_t mtu); diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c index 247503d094..2377d66e65 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c @@ -2331,6 +2331,13 @@ void l2ble_update_att_acl_pkt_num(UINT8 type, tl2c_buff_param_t *param) xSemaphoreGive(buff_semaphore); break; } + + if (!gatt_check_connection_state_by_tcb(p_tcb)) { + L2CAP_TRACE_ERROR("connection not established\n"); + xSemaphoreGive(buff_semaphore); + break; + } + tL2C_LCB * p_lcb = l2cu_find_lcb_by_bd_addr (p_tcb->peer_bda, BT_TRANSPORT_LE); if (p_lcb == NULL){ L2CAP_TRACE_ERROR("%s not found p_lcb", __func__);