Skip to content

L2CAP: CoC RX double-free corrupts mempool leading to os_memblock_get crash #2142

@mickeyl

Description

@mickeyl

Disclaimer: This has been created with the help of an LLM when I had crashes in my app using L2CAP channels between Apple and ESP32S3 devices.

  • Environment: ESP-IDF v5.5.1 NimBLE host
  • Steps to reproduce: Use CoC, receive an SDU, hand mbuf to app, later disconnect/cleanup; under load the crash occurs in os_memblock_get (os_mempool.c:360).
  • Root cause: In ble_l2cap_coc_rx_fn, when an SDU completes, the pointer remains in chan->coc_rx.sdus[]. The application owns the mbuf and frees it. On disconnect, ble_l2cap_coc_cleanup_chan() frees all non-null slots again, double-freeing a block that may already be back on the free list → mempool corruption → crash.
  • Fix idea: Clear the slot when handing the SDU to the app.
  • Result: Prevents cleanup from freeing application-owned mbufs; resolves the os_memblock_get crash under high-rate CoC traffic.

Diff:

diff --git a/nimble/host/src/ble_l2cap_coc.c b/nimble/host/src/ble_l2cap_coc.c
index 21c91ef0..fc9409f8 100644
--- a/nimble/host/src/ble_l2cap_coc.c
+++ b/nimble/host/src/ble_l2cap_coc.c
@@ -279,10 +279,10 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
         BLE_HS_LOG(DEBUG, "Received sdu_len=%d, credits left=%d\n",
                    OS_MBUF_PKTLEN(rx_sdu), rx->credits);

-        /* Lets get back control to os_mbuf to application.
-         * Since it this callback application might want to set new sdu
-         * we need to prepare space for this. Therefore we need sdu_rx
+        /* Hand off ownership of the completed SDU to the application and clear
+         * the slot so cleanup code will not attempt to free it again.
          */
+        rx->sdus[chan->coc_rx.current_sdu_idx] = NULL;
         rx_sdu = NULL;
         chan->coc_rx.current_sdu_idx =
             (chan->coc_rx.current_sdu_idx + 1) % BLE_L2CAP_SDU_BUFF_CNT;

I must confess I don't know whether this makes sense, but it fixed one of my issues, so I figured I might as well report it.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions