All of lore.kernel.org
 help / color / mirror / Atom feed
From: bugzilla-daemon@kernel.org
To: linux-bluetooth@vger.kernel.org
Subject: [Bug 221629] New: Bluetooth l2cap: ident leak in l2cap_chan_le_send_credits() stalls BLE CoC
Date: Tue, 09 Jun 2026 17:58:02 +0000	[thread overview]
Message-ID: <bug-221629-62941@https.bugzilla.kernel.org/> (raw)

https://bugzilla.kernel.org/show_bug.cgi?id=221629

            Bug ID: 221629
           Summary: Bluetooth l2cap: ident leak in
                    l2cap_chan_le_send_credits() stalls BLE CoC
           Product: Drivers
           Version: 2.5
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P3
         Component: Bluetooth
          Assignee: linux-bluetooth@vger.kernel.org
          Reporter: florian-evers@gmx.de
        Regression: No

Hi,

I have found a resource leak in l2cap_chan_le_send_credits() that causes
permanent stalls of BLE L2CAP Connection-Oriented Channels under sustained
traffic. Here, I couple two Linux computers using a long-lasting L2CAP CoC
channel and transmit data in both directions, but the stream freezes after a
few seconds with dmesg warnings.


Root Cause:
-----------
l2cap_chan_le_send_credits() allocates an ident via l2cap_get_ident(conn)
(which does ida_alloc_range on conn->tx_ida), then sends L2CAP_LE_CREDITS.

However, L2CAP_LE_CREDITS is a unidirectional signaling command; the remote
never sends a response.
The normal ident-free path (l2cap_put_ident via l2cap_le_sig_cmd) is only
triggered when a response opcode arrives.
Since no response exists for this opcode, the ident is never freed.

The kernel itself documents this as unexpected at line 950-954:

    /* If all idents are in use, log an error, this is
     * extremely unlikely to happen and would indicate a bug
     * in the code that idents are not being freed properly.
     */

Failure Chain:
--------------
1. Each received SDU triggers credit replenishment at
l2cap_chan_le_send_credits()
2. Each call leaks one ident slot from the 255-slot tx_ida pool
3. After 255 credits sent, ida_alloc_range returns -ENOSPC
4. l2cap_get_ident() returns 0, logs "Unable to allocate ident: -28"
5. No further credit updates can be sent
6. Remote's TX credit window drains to zero resulting in a permanent write
stall


My assumption: why it was never found yet
-----------
- This issue only affects the RECEIVING side (which must send credit updates).
  The sending side never calls l2cap_chan_le_send_credits().
- The pool has 255 slots, so it takes 255 SDUs to exhaust, and short test
sessions may never trigger it.
- Classic Bluetooth L2CAP uses a separate ident range (1-128) with
request/response pairs, so it is not affected.


How to Reproduce:
-----------------
Any sustained unidirectional BLE L2CAP CoC data stream where Linux is the
receiver is affected.
Transfer >255 SDUs (e.g., a 200 KB file at MPS=512 triggers ~400 credit
updates). After exhaustion, dmesg shows:

    Bluetooth: Unable to allocate ident: -28

and all signaling on that connection stops permanently. The stream freezes.

I have that issue on a self-compiled kernel 7.0.10-gentoo.


Proposed  Fix:
--------------
The ident can be freed immediately after l2cap_send_cmd(), since no response
will ever reference it:

--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6652,6 +6652,18 @@
 chan->ident = l2cap_get_ident(conn);

 l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
+
+/* L2CAP_LE_CREDITS is a one-way indication: the remote never sends a
+ * response, so l2cap_put_ident() is never called for this ident.
+ * Free it immediately to prevent exhausting the 255-slot tx_ida pool
+ * under sustained CoC traffic (e.g. hours-long bulk data streams).
+ * Pool exhaustion causes credit updates to stop being sent, which
+ * drains the remote TX credit window to zero and permanently stalls
+ * all data transfer in both directions.
+ */
+if (chan->ident)
+ida_free(&conn->tx_ida, chan->ident);
+chan->ident = 0;
 }

This fix has been running here for 1-2 weeks without any issues. Data is
flowing now without any dmesg warnings or stalls.

Kind regards,
Florian Evers

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

             reply	other threads:[~2026-06-09 17:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-09 17:58 bugzilla-daemon [this message]
2026-06-09 17:58 ` [Bug 221629] Bluetooth l2cap: ident leak in l2cap_chan_le_send_credits() stalls BLE CoC bugzilla-daemon
2026-06-09 17:59 ` bugzilla-daemon
2026-06-09 18:09 ` bugzilla-daemon
2026-06-09 18:17 ` bugzilla-daemon
2026-06-09 19:04 ` [Bug,221629] New: " bluez.test.bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-221629-62941@https.bugzilla.kernel.org/ \
    --to=bugzilla-daemon@kernel.org \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.