Skip to content

Commit e7fee6f

Browse files
committed
Fix CoC tx mbuf ownership on transient send errors
Handle ENOMEM/EAGAIN from `ble_l2cap_send` as “mbuf consumed” and only free tx buffers on EBUSY; prevents double-free pool corruption during CoC stress. ESP-IDF NimBLE host change needed separately: In components/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c, when an SDU completes (RX path), clear rx->sdus[current_sdu_idx] = NULL before advancing the index so cleanup won’t free a buffer already handed to the application.
1 parent f3559e4 commit e7fee6f

1 file changed

Lines changed: 7 additions & 1 deletion

File tree

src/NimBLEL2CAPChannel.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin
134134

135135
case BLE_HS_ENOMEM:
136136
case BLE_HS_EAGAIN:
137+
/* ble_l2cap_send already consumed and freed txd on these errors */
138+
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (consumed buffer). Retrying shortly...", res);
139+
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
140+
continue;
141+
137142
case BLE_HS_EBUSY:
138-
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d. Retrying shortly...", res);
143+
/* Channel busy; txd not consumed */
144+
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (busy). Retrying shortly...", res);
139145
os_mbuf_free_chain(txd);
140146
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
141147
continue;

0 commit comments

Comments
 (0)