mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
fix(bt/bluedroid): fixed heap corruption when deinit A2DP/HID during SDP discovery
Cancel in-flight SDP searches before freeing discovery databases in BTA AV and HID Host. Otherwise a late SDP response can be parsed into a freed buffer after esp_a2d_*_deinit / HID host disable, the same class of corruption as JV/SPP deinit. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user