mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
fix(bt_stack): Fix some critical bugs in classic_bt stack
related: obex, smp, pbap, sdp, rfcomm, stack_dm - Deinit function doesn't delete connection when OBEX_DYNAMIC_MEMORY is on - Union tGOEPC_DATA sometimes is free by osi_free in some cases when it contains mtu_id - Add correct free and return solution after fail - Fix symbol mistake in mod calculation - Fix pointer-related UAF problems and memory free problems - Fix buffer overflows and out-of-bounds access - Fix infinite loops triggered by integer overflow wraparound - Fix double free - Change layer_specific usage to avoid heap overflow - Add some NULL check for pointers - Fix sdp_db free function - Fix state table mismatch
This commit is contained in:
@@ -85,7 +85,7 @@ typedef union
|
||||
typedef void (tOBEX_TL_CBACK)(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg);
|
||||
|
||||
typedef struct {
|
||||
void (*init)(tOBEX_TL_CBACK *callback);
|
||||
UINT16 (*init)(tOBEX_TL_CBACK *callback);
|
||||
void (*deinit)(void);
|
||||
UINT16 (*connect)(tOBEX_TL_SVR_INFO *server);
|
||||
void (*disconnect)(UINT16 tl_hdl);
|
||||
|
||||
@@ -67,12 +67,16 @@ UINT16 OBEX_Init(void)
|
||||
memset(&obex_cb, 0, sizeof(tOBEX_CB));
|
||||
obex_cb.tl_ops[OBEX_OVER_L2CAP] = obex_tl_l2cap_ops_get();
|
||||
if (obex_cb.tl_ops[OBEX_OVER_L2CAP] && obex_cb.tl_ops[OBEX_OVER_L2CAP]->init) {
|
||||
obex_cb.tl_ops[OBEX_OVER_L2CAP]->init(obex_tl_l2cap_callback);
|
||||
if (obex_cb.tl_ops[OBEX_OVER_L2CAP]->init(obex_tl_l2cap_callback) == 0) {
|
||||
return OBEX_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#if (RFCOMM_INCLUDED == TRUE)
|
||||
obex_cb.tl_ops[OBEX_OVER_RFCOMM] = obex_tl_rfcomm_ops_get();
|
||||
if (obex_cb.tl_ops[OBEX_OVER_RFCOMM] && obex_cb.tl_ops[OBEX_OVER_RFCOMM]->init) {
|
||||
obex_cb.tl_ops[OBEX_OVER_RFCOMM]->init(obex_tl_rfcomm_callback);
|
||||
if(obex_cb.tl_ops[OBEX_OVER_RFCOMM]->init(obex_tl_rfcomm_callback) == 0) {
|
||||
return OBEX_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
obex_cb.trace_level = BT_TRACE_LEVEL_ERROR;
|
||||
@@ -89,16 +93,18 @@ UINT16 OBEX_Init(void)
|
||||
*******************************************************************************/
|
||||
void OBEX_Deinit(void)
|
||||
{
|
||||
if (obex_cb.tl_ops[OBEX_OVER_L2CAP] && obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit) {
|
||||
obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit();
|
||||
}
|
||||
#if (RFCOMM_INCLUDED == TRUE)
|
||||
if (obex_cb.tl_ops[OBEX_OVER_RFCOMM] && obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit) {
|
||||
obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit();
|
||||
}
|
||||
#endif
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
if (obex_cb_ptr) {
|
||||
#endif
|
||||
if (obex_cb.tl_ops[OBEX_OVER_L2CAP] && obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit) {
|
||||
obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit();
|
||||
}
|
||||
#if (RFCOMM_INCLUDED == TRUE)
|
||||
if (obex_cb.tl_ops[OBEX_OVER_RFCOMM] && obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit) {
|
||||
obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit();
|
||||
}
|
||||
#endif
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
osi_free(obex_cb_ptr);
|
||||
obex_cb_ptr = NULL;
|
||||
}
|
||||
@@ -325,6 +331,9 @@ UINT16 OBEX_BuildRequest(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out_
|
||||
if (buff_size < OBEX_MIN_PACKET_SIZE || info == NULL || out_pkt == NULL) {
|
||||
return OBEX_INVALID_PARAM;
|
||||
}
|
||||
if (UINT16_MAX - buff_size < sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN) {
|
||||
return OBEX_NO_RESOURCES;
|
||||
}
|
||||
buff_size += sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN;
|
||||
|
||||
BT_HDR *p_buf = (BT_HDR *)osi_malloc(buff_size);
|
||||
@@ -386,6 +395,9 @@ UINT16 OBEX_BuildResponse(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out
|
||||
if (buff_size < OBEX_MIN_PACKET_SIZE || info == NULL || out_pkt == NULL) {
|
||||
return OBEX_INVALID_PARAM;
|
||||
}
|
||||
if (0xFFFF - buff_size < sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN) {
|
||||
return OBEX_NO_RESOURCES;
|
||||
}
|
||||
buff_size += sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN;
|
||||
|
||||
BT_HDR *p_buf= (BT_HDR *)osi_malloc(buff_size);
|
||||
|
||||
@@ -554,7 +554,7 @@ void obex_tl_l2cap_congestion_status_ind(UINT16 lcid, BOOLEAN is_congested)
|
||||
** other APIs
|
||||
**
|
||||
*******************************************************************************/
|
||||
void obex_tl_l2cap_init(tOBEX_TL_CBACK *callback)
|
||||
UINT16 obex_tl_l2cap_init(tOBEX_TL_CBACK *callback)
|
||||
{
|
||||
assert(callback != NULL);
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
@@ -562,7 +562,7 @@ void obex_tl_l2cap_init(tOBEX_TL_CBACK *callback)
|
||||
obex_tl_l2cap_cb_ptr = (tOBEX_TL_L2CAP_CB *)osi_malloc(sizeof(tOBEX_TL_L2CAP_CB));
|
||||
if (!obex_tl_l2cap_cb_ptr) {
|
||||
OBEX_TL_L2CAP_TRACE_ERROR("OBEX over L2CAP transport layer initialize failed, no memory\n");
|
||||
assert(0);
|
||||
return OBEX_TL_FAILED;
|
||||
}
|
||||
}
|
||||
#endif /* #if (OBEX_DYNAMIC_MEMORY) */
|
||||
@@ -583,6 +583,7 @@ void obex_tl_l2cap_init(tOBEX_TL_CBACK *callback)
|
||||
p_reg_info->pL2CA_DataInd_Cb = obex_tl_l2cap_buf_data_ind;
|
||||
p_reg_info->pL2CA_CongestionStatus_Cb = obex_tl_l2cap_congestion_status_ind;
|
||||
p_reg_info->pL2CA_TxComplete_Cb = NULL;
|
||||
return OBEX_TL_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -276,7 +276,7 @@ static void rfcomm_event_callback(UINT32 code, UINT16 rfc_handle)
|
||||
}
|
||||
}
|
||||
|
||||
void obex_tl_rfcomm_init(tOBEX_TL_CBACK *callback)
|
||||
UINT16 obex_tl_rfcomm_init(tOBEX_TL_CBACK *callback)
|
||||
{
|
||||
assert(callback != NULL);
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
@@ -284,19 +284,32 @@ void obex_tl_rfcomm_init(tOBEX_TL_CBACK *callback)
|
||||
obex_tl_rfcomm_cb_ptr = (tOBEX_TL_RFCOMM_CB *)osi_malloc(sizeof(tOBEX_TL_RFCOMM_CB));
|
||||
if (!obex_tl_rfcomm_cb_ptr) {
|
||||
OBEX_TL_RFCOMM_TRACE_ERROR("OBEX over RFCOMM transport layer initialize failed, no memory\n");
|
||||
assert(0);
|
||||
return OBEX_TL_FAILED;
|
||||
}
|
||||
}
|
||||
#endif /* #if (OBEX_DYNAMIC_MEMORY) */
|
||||
memset(&obex_tl_rfcomm_cb, 0, sizeof(tOBEX_TL_RFCOMM_CB));
|
||||
obex_tl_rfcomm_cb.callback = callback;
|
||||
obex_tl_rfcomm_cb.trace_level = BT_TRACE_LEVEL_ERROR;
|
||||
return OBEX_TL_SUCCESS;
|
||||
}
|
||||
|
||||
void obex_tl_rfcomm_deinit(void)
|
||||
{
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
if (obex_tl_rfcomm_cb_ptr) {
|
||||
#endif
|
||||
for (size_t i = 0; i < OBEX_TL_RFCOMM_NUM_CONN; i++) {
|
||||
if (obex_tl_rfcomm_cb.ccb[i].rfc_handle != 0) {
|
||||
RFCOMM_RemoveConnection(obex_tl_rfcomm_cb.ccb[i].rfc_handle);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < OBEX_TL_RFCOMM_NUM_SERVER; i++) {
|
||||
if (obex_tl_rfcomm_cb.scb[i].rfc_handle != 0) {
|
||||
RFCOMM_RemoveServer(obex_tl_rfcomm_cb.scb[i].rfc_handle);
|
||||
}
|
||||
}
|
||||
#if (OBEX_DYNAMIC_MEMORY)
|
||||
osi_free(obex_tl_rfcomm_cb_ptr);
|
||||
obex_tl_rfcomm_cb_ptr = NULL;
|
||||
}
|
||||
@@ -357,8 +370,6 @@ UINT16 obex_tl_rfcomm_send(UINT16 handle, BT_HDR *p_buf)
|
||||
|
||||
if (PORT_Write(p_ccb->rfc_handle, p_buf) == PORT_SUCCESS) {
|
||||
ret = OBEX_TL_SUCCESS;
|
||||
} else {
|
||||
osi_free(p_buf);
|
||||
}
|
||||
} while (0);
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user