Merge branch 'fix/fix_blufi_memory_copy_len_error_v5.4' into 'release/v5.4'

fix(ble): Fix blufi fragment reassembly bounds and buffer overflows (5.4)

See merge request espressif/esp-idf!48266
This commit is contained in:
Island
2026-05-12 19:27:41 +08:00
28 changed files with 1005 additions and 201 deletions
@@ -461,11 +461,10 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec)
return;
}
}
osi_mutex_unlock(&btu_general_alarm_lock);
alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_ERROR("%s Unable to create alarm", __func__);
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
@@ -475,6 +474,7 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec)
p_tle->ticks = timeout_sec;
p_tle->in_use = TRUE;
osi_alarm_set(alarm, (period_ms_t)((period_ms_t)timeout_sec * 1000));
osi_mutex_unlock(&btu_general_alarm_lock);
}
@@ -491,18 +491,21 @@ void btu_stop_timer(TIMER_LIST_ENT *p_tle)
{
assert(p_tle != NULL);
osi_mutex_lock(&btu_general_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (p_tle->in_use == FALSE) {
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
p_tle->in_use = FALSE;
// Get the alarm for the timer list entry.
osi_alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_general_alarm_lock);
}
/*******************************************************************************
@@ -518,16 +521,18 @@ void btu_free_timer(TIMER_LIST_ENT *p_tle)
{
assert(p_tle != NULL);
p_tle->in_use = FALSE;
// Get the alarm for the timer list entry.
osi_mutex_lock(&btu_general_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
osi_alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_DEBUG("%s Unable to find expected alarm in hashmap", __func__);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
hash_map_erase(btu_general_alarm_hash_map, p_tle);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_general_alarm_lock);
}
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
@@ -586,11 +591,10 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti
return;
}
}
osi_mutex_unlock(&btu_l2cap_alarm_lock);
alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_ERROR("%s Unable to create alarm", __func__);
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
@@ -600,6 +604,7 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti
p_tle->in_use = TRUE;
// The quick timer ticks are 100ms long.
osi_alarm_set(alarm, (period_ms_t)(timeout_ticks * 100));
osi_mutex_unlock(&btu_l2cap_alarm_lock);
}
/*******************************************************************************
@@ -615,34 +620,39 @@ void btu_stop_quick_timer(TIMER_LIST_ENT *p_tle)
{
assert(p_tle != NULL);
osi_mutex_lock(&btu_l2cap_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (p_tle->in_use == FALSE) {
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
p_tle->in_use = FALSE;
// Get the alarm for the timer list entry.
osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_l2cap_alarm_lock);
}
void btu_free_quick_timer(TIMER_LIST_ENT *p_tle)
{
assert(p_tle != NULL);
p_tle->in_use = FALSE;
// Get the alarm for the timer list entry.
osi_mutex_lock(&btu_l2cap_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_DEBUG("%s Unable to find expected alarm in hashmap", __func__);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
hash_map_erase(btu_l2cap_alarm_hash_map, p_tle);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_l2cap_alarm_lock);
}
#endif /* defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) */
@@ -682,11 +692,10 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_
return;
}
}
osi_mutex_unlock(&btu_oneshot_alarm_lock);
alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_ERROR("%s Unable to create alarm", __func__);
osi_mutex_unlock(&btu_oneshot_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
@@ -696,24 +705,28 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_
// NOTE: This value is in seconds but stored in a ticks field.
p_tle->ticks = timeout_sec;
osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000));
osi_mutex_unlock(&btu_oneshot_alarm_lock);
}
void btu_stop_timer_oneshot(TIMER_LIST_ENT *p_tle)
{
assert(p_tle != NULL);
osi_mutex_lock(&btu_oneshot_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (p_tle->in_use == FALSE) {
osi_mutex_unlock(&btu_oneshot_alarm_lock);
return;
}
p_tle->in_use = FALSE;
// Get the alarm for the timer list entry.
osi_alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
if (alarm == NULL) {
HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_oneshot_alarm_lock);
return;
}
osi_alarm_cancel(alarm);
p_tle->in_use = FALSE;
osi_mutex_unlock(&btu_oneshot_alarm_lock);
}
#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)