Merge branch 'bugfix/spp_deinit_crash_v6.0' into 'release/v6.0'

fix(bt/bluedroid): fixed heap corruption when deinit profiles during SDP discovery(v6.0)

See merge request espressif/esp-idf!53062
This commit is contained in:
Jiang Jiang Jian
2026-09-23 12:03:38 +08:00
6 changed files with 59 additions and 10 deletions
@@ -35,6 +35,7 @@
#include "bta_av_int.h"
#include "stack/avdt_api.h"
#include "stack/sdp_api.h"
#include "bta/utl.h"
#include "stack/l2c_api.h"
#include "stack/l2cdefs.h"
@@ -1035,7 +1036,7 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
/* free any buffers */
utl_freebuf((void **) &p_scb->p_cap);
utl_freebuf((void **) &p_scb->p_disc_db);
bta_av_free_sdb(p_scb, NULL);
p_scb->avdt_version = 0;
/* initialize some control block variables */
@@ -1082,7 +1083,10 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
void bta_av_free_sdb(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
{
UNUSED(p_data);
utl_freebuf((void **) &p_scb->p_disc_db);
if (p_scb->p_disc_db) {
SDP_CancelServiceSearch(p_scb->p_disc_db);
utl_freebuf((void **) &p_scb->p_disc_db);
}
}
/*******************************************************************************
@@ -1586,7 +1590,7 @@ void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
{
UNUSED(p_data);
utl_freebuf((void **) &p_scb->p_disc_db);
bta_av_free_sdb(p_scb, NULL);
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
/* SNK initiated L2C connection while SRC was doing SDP. */
@@ -1613,7 +1617,7 @@ void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_scb->open_status = BTA_AV_FAIL_SDP;
}
utl_freebuf((void **) &p_scb->p_disc_db);
bta_av_free_sdb(p_scb, NULL);
bta_av_str_closed(p_scb, p_data);
}
@@ -31,6 +31,7 @@
#include "bta_av_int.h"
#include "stack/avdt_api.h"
#include "bta/utl.h"
#include "stack/sdp_api.h"
#include "stack/l2c_api.h"
#include "osi/allocator.h"
#include "osi/list.h"
@@ -1302,7 +1303,14 @@ void bta_av_disable(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
bta_av_close_all_rc(p_cb);
utl_freebuf((void **) &p_cb->p_disc_db);
/* Clear disc first so a late BTA_AV_SDP_AVRC_DISC_EVT hits
* bta_av_rc_disc_done()'s if (!p_cb->disc) and does not scan p_disc_db. */
p_cb->disc = 0;
if (p_cb->p_disc_db) {
/* SDP may still be writing into this buffer (AVRCP discovery). */
SDP_CancelServiceSearch(p_cb->p_disc_db);
utl_freebuf((void **) &p_cb->p_disc_db);
}
/* disable audio/video - de-register all channels,
* expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
@@ -1757,7 +1765,10 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
}
#endif
p_cb->disc = 0;
utl_freebuf((void **) &p_cb->p_disc_db);
if (p_cb->p_disc_db) {
SDP_CancelServiceSearch(p_cb->p_disc_db);
utl_freebuf((void **) &p_cb->p_disc_db);
}
APPL_TRACE_DEBUG("peer_features 0x%x, local features 0x%x", peer_features, p_cb->features);
@@ -35,6 +35,7 @@
#include "bta/bta_hh_co.h"
#include "bta/utl.h"
#include "osi/allocator.h"
#include "stack/sdp_api.h"
/*****************************************************************************
** Constants
@@ -129,6 +130,9 @@ void bta_hh_api_disable(void)
return;
}
/* Drop in-flight SDP before tearing down connections / HID host. */
bta_hh_free_disc_db();
/* no live connection, signal DISC_CMPL_EVT directly */
if (!bta_hh_cb.cnt_num) {
bta_hh_disc_cmpl();
@@ -243,7 +247,7 @@ static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
}
/* free disc_db when SDP is completed */
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
bta_hh_free_disc_db();
/* send SDP_CMPL_EVT into state machine */
data.status = status;
@@ -301,7 +305,7 @@ static void bta_hh_di_sdp_cback(UINT16 result)
if (status != BTA_HH_OK) {
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
bta_hh_free_disc_db();
/* send SDP_CMPL_EVT into state machine */
data.status = status;
bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &data);
@@ -384,7 +388,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
Status 0x%2X", status);
#endif
status = BTA_HH_ERR_SDP;
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
bta_hh_free_disc_db();
} else {
status = BTA_HH_OK;
}
@@ -22,6 +22,7 @@
#include "osi/allocator.h"
#include "bta_hh_int.h"
#include "stack/sdp_api.h"
/* if SSR max latency is not defined by remote device, set the default value
as half of the link supervision timeout */
@@ -462,6 +463,25 @@ tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UIN
return status;
}
/*******************************************************************************
**
** Function bta_hh_free_disc_db
**
** Description Cancel any in-flight SDP search using the HID discovery
** database, then free it.
**
** Returns void
**
*******************************************************************************/
void bta_hh_free_disc_db(void)
{
if (bta_hh_cb.p_disc_db) {
/* SDP (DI discover / HID_HostGetSDPRecord) may still write this buffer. */
SDP_CancelServiceSearch(bta_hh_cb.p_disc_db);
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
}
}
/*******************************************************************************
**
** Function bta_hh_cleanup_disable
@@ -479,7 +499,7 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) {
utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
}
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
bta_hh_free_disc_db();
bta_sys_deregister(BTA_ID_HH);
@@ -356,6 +356,7 @@ extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
UINT16 version, UINT8 flag);
extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status);
extern void bta_hh_free_disc_db(void);
extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle);
@@ -754,6 +754,15 @@ void bta_jv_disable (tBTA_JV_MSG *p_data)
tBTA_JV_STATUS evt_data;
evt_data = BTA_JV_SUCCESS;
/* An SDP search still in progress keeps writing into p_bta_jv_cfg->p_sdp_db,
* which BTA_JvFree() releases once BTA_JV_DISABLE_EVT is handled. Cancel it
* first: the connection control block then rejects any late response instead
* of parsing it into freed memory. */
if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
APPL_TRACE_WARNING("%s: SDP discovery active, cancelling it", __func__);
SDP_CancelServiceSearch(p_bta_jv_cfg->p_sdp_db);
}
// clear all the pm_cb slots
for (int i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
if (bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) {