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:
hejiaxin
2026-07-29 17:05:31 +08:00
parent 52ffcbf270
commit 7f42eabb08
27 changed files with 177 additions and 73 deletions
@@ -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;