* [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
@ 2026-10-13 3:19 Kyle Pepper
2026-10-13 4:20 ` [RFC] " bluez.test.bot
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-10-13 3:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-kernel
A nonconforming ASHA peer sends identifier-zero credit indications
that are discarded, reducing usable transmit credits until audio stalls.
Tolerate only exact-size credit indications for a connected LE CoC.
Preserve the channel reference, lock and credit-overflow checks and do
not send a response with identifier zero. Other zero-ID commands and
BR/EDR signaling remain unchanged.
Core Vol 3 Part A section 4 forbids identifier zero. This is an
interoperability RFC requiring maintainer agreement, not a conformance
fix or a claim of automatic stream recovery.
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Submission review notes (not part of the commit message):
Core specification forbids identifier zero. This is a narrow opcode
interoperability exception, not a conformance fix. N8 captures contain
zero-ID credit indications. Native malformed/overflow/teardown and
lockdep/KASAN coverage and exception policy remain review gates.
net/bluetooth/l2cap_core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 49a998804..1a0868437 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5328,6 +5328,12 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
l2cap_chan_lock(chan);
+ /* Tolerate identifier-zero credits only for a live LE CoC. */
+ if (!cmd->ident &&
+ (!credits || chan->state != BT_CONNECTED ||
+ chan->mode != L2CAP_MODE_LE_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5923,11 +5929,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
- if (len != skb->len || !cmd->ident) {
+ if (len != skb->len) {
BT_DBG("corrupted command");
goto drop;
}
+ if (!cmd->ident) {
+ if (cmd->code != L2CAP_LE_CREDITS ||
+ len != sizeof(struct l2cap_le_credits))
+ goto drop;
+
+ /* Credits have no response or identifier-matched transaction. */
+ l2cap_le_credits(conn, cmd, len, skb->data);
+ goto drop;
+ }
+
err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
base-commit: 964430c038967fd06643e866f68115664e1a1bd1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* RE: [RFC] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-13 3:19 [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
@ 2026-10-13 4:20 ` bluez.test.bot
2026-10-13 14:43 ` [RFC PATCH] " Luiz Augusto von Dentz
2026-10-15 5:28 ` [RFC PATCH v2] " Kyle Pepper
2 siblings, 0 replies; 15+ messages in thread
From: bluez.test.bot @ 2026-10-13 4:20 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 1073 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1184328/
---Test result---
Test Summary:
CheckPatch PASS 0.52 seconds
VerifyFixes PASS 0.08 seconds
VerifySignedoff PASS 0.08 seconds
GitLint PASS 0.23 seconds
SubjectPrefix PASS 0.07 seconds
BuildKernel PASS 21.37 seconds
CheckAllWarning PASS 25.54 seconds
CheckSparse PASS 27.19 seconds
BuildKernel32 PASS 22.33 seconds
CheckKernelLLVM PASS 24.27 seconds
TestRunnerSetup PASS 508.85 seconds
TestRunner_l2cap-tester PASS 13.31 seconds
IncrementalBuild PASS 20.81 seconds
https://github.com/bluez/bluetooth-next/pull/907
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-13 3:19 [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-10-13 4:20 ` [RFC] " bluez.test.bot
@ 2026-10-13 14:43 ` Luiz Augusto von Dentz
2026-10-15 18:31 ` cochcoder
2026-10-15 5:28 ` [RFC PATCH v2] " Kyle Pepper
2 siblings, 1 reply; 15+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-13 14:43 UTC (permalink / raw)
To: Kyle Pepper; +Cc: linux-bluetooth, Marcel Holtmann, linux-kernel
Hi Kyle,
On Mon, Oct 12, 2026 at 11:20 PM Kyle Pepper <cochcoder@proton.me> wrote:
>
> A nonconforming ASHA peer sends identifier-zero credit indications
> that are discarded, reducing usable transmit credits until audio stalls.
>
> Tolerate only exact-size credit indications for a connected LE CoC.
> Preserve the channel reference, lock and credit-overflow checks and do
> not send a response with identifier zero. Other zero-ID commands and
> BR/EDR signaling remain unchanged.
>
> Core Vol 3 Part A section 4 forbids identifier zero. This is an
> interoperability RFC requiring maintainer agreement, not a conformance
> fix or a claim of automatic stream recovery.
>
> Assisted-by: OpenCode:gpt-6.1-sol
> Signed-off-by: Kyle Pepper <cochcoder@proton.me>
> ---
> Submission review notes (not part of the commit message):
> Core specification forbids identifier zero. This is a narrow opcode
> interoperability exception, not a conformance fix. N8 captures contain
> zero-ID credit indications. Native malformed/overflow/teardown and
> lockdep/KASAN coverage and exception policy remain review gates.
>
> net/bluetooth/l2cap_core.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 49a998804..1a0868437 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -5328,6 +5328,12 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
>
> l2cap_chan_lock(chan);
>
> + /* Tolerate identifier-zero credits only for a live LE CoC. */
> + if (!cmd->ident &&
> + (!credits || chan->state != BT_CONNECTED ||
> + chan->mode != L2CAP_MODE_LE_FLOWCTL))
> + goto unlock;
> +
> max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
> if (credits > max_credits) {
> BT_ERR("LE credits overflow");
> @@ -5923,11 +5929,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
>
> BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
>
> - if (len != skb->len || !cmd->ident) {
> + if (len != skb->len) {
> BT_DBG("corrupted command");
> goto drop;
> }
>
> + if (!cmd->ident) {
> + if (cmd->code != L2CAP_LE_CREDITS ||
> + len != sizeof(struct l2cap_le_credits))
> + goto drop;
> +
> + /* Credits have no response or identifier-matched transaction. */
> + l2cap_le_credits(conn, cmd, len, skb->data);
> + goto drop;
> + }
> +
> err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
> if (err) {
> struct l2cap_cmd_rej_unk rej;
>
> base-commit: 964430c038967fd06643e866f68115664e1a1bd1
Sashiko flagged a problem with this:
https://sashiko.dev/#/patchset/20261013031943.489829-1-cochcoder%40proton.me
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH v2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-13 3:19 [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-10-13 4:20 ` [RFC] " bluez.test.bot
2026-10-13 14:43 ` [RFC PATCH] " Luiz Augusto von Dentz
@ 2026-10-15 5:28 ` Kyle Pepper
2026-10-15 6:42 ` [RFC,v2] " bluez.test.bot
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
2 siblings, 2 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-10-15 5:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-kernel
Tolerate exact-size, nonzero credit grants with identifier zero only
for connected LE credit-based channels. Keep the target and pending
security checks shared with ordinary identifiers. Do not send a
response with identifier zero or relax other signaling commands.
This is an interoperability exception to Core Vol 3 Part A section 4,
not a conformance fix.
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Changes since v1:
- Depend on the separately submitted target/state and pending-security fix.
- Require a connected ordinary LE CoC, an exact-size indication and a nonzero
grant. Keep fixed/unready targets and ECRED identifier-zero grants excluded.
- Preserve shared target/security checks for normal and zero identifiers.
- Do not generate any response with identifier zero or relax other commands.
REQUIRED security dependency, submitted separately and not resent here:
https://lore.kernel.org/linux-bluetooth/20261015052018.129971-1-cochcoder@proton.me/
Signed dependency commit: 61a7ca610078ddf616873e7d4914cb6ac9eae7a3.
Apply it first. This mail includes its prerequisite patch-id against upstream
397464709a20. The resulting source tree matches the validated refreshed pair.
The Core specification still forbids identifier zero. This remains an
interoperability RFC requiring maintainer policy agreement, not a conformance
fix. The separate security patch is independently useful without this exception.
Fresh current-base controls: all nine focused security cases pass with either
security-only or combined kernels. Public credit controls pass 13/14 with
security-only (expected positive zero-ID failure), and 14/14 with this revision
added. No skips or captured KASAN/lockdep alerts occurred in these focused runs.
GCC W=1 changed objects and source-extracted security/target/zero-ID fixtures pass.
The refreshed full suite is NOT claimed passing: SCI Fast Mode encounters an
invalid response length for HCI opcode 0x20a3 and times out without a complete
summary. The same SCI failure reproduces on unpatched current upstream and both
revised guests. Initial spaced VM selectors selected broader tests; corrected
space-free credit runs are the focused results above. Earlier 134/134 combined
results belong to the older reference base, not this fresh full-suite attempt.
The combined Arch integration is reported working on hardware, not isolated
attribution or exhaustive device/security/teardown coverage. No remote CI pass
or severity claim is made. Private security reproducer/logs are not included.
Confirm archive rendering of the dependency link before sending.
net/bluetooth/l2cap_core.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7a7f30531..d805b1c62 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5396,6 +5396,10 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->mode != L2CAP_MODE_EXT_FLOWCTL))
goto unlock;
+ /* Tolerate identifier-zero credits only for a live LE CoC. */
+ if (!cmd->ident && (!credits || chan->mode != L2CAP_MODE_LE_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5994,11 +5998,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
- if (len != skb->len || !cmd->ident) {
+ if (len != skb->len) {
BT_DBG("corrupted command");
goto drop;
}
+ if (!cmd->ident) {
+ if (cmd->code != L2CAP_LE_CREDITS ||
+ len != sizeof(struct l2cap_le_credits))
+ goto drop;
+
+ /* Credits have no response or identifier-matched transaction. */
+ l2cap_le_credits(conn, cmd, len, skb->data);
+ goto drop;
+ }
+
err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
base-commit: 397464709a204da9b8dc3b01d6ea42539d951cd2
prerequisite-patch-id: 658bb8f3b3e38bbbb21f2619434affc641582b7f
^ permalink raw reply related [flat|nested] 15+ messages in thread
* RE: [RFC,v2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-15 5:28 ` [RFC PATCH v2] " Kyle Pepper
@ 2026-10-15 6:42 ` bluez.test.bot
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
1 sibling, 0 replies; 15+ messages in thread
From: bluez.test.bot @ 2026-10-15 6:42 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 851 bytes --]
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.
----- Output -----
error: patch failed: net/bluetooth/l2cap_core.c:5396
error: net/bluetooth/l2cap_core.c: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Please resolve the issue and submit the patches again.
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-10-15 5:28 ` [RFC PATCH v2] " Kyle Pepper
2026-10-15 6:42 ` [RFC,v2] " bluez.test.bot
@ 2026-10-15 18:16 ` Kyle Pepper
2026-10-15 18:17 ` [RFC PATCH v3 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
` (3 more replies)
1 sibling, 4 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-10-15 18:16 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Johan Hedberg,
linux-kernel
Credit indications can invoke resume on fixed or unready channels.
Connected LE credit-based sockets can also resume during a security
upgrade because credits and security share the socket suspend flag.
Validate the target mode and state for every identifier. Track pending
LE/ECRED security upgrades and retain credits without sending queued
data or resuming the socket until encryption meets the requested level.
Drain queued data after security completes and keep credit-starved
sockets suspended.
Fixes: fad5fc89594d ("Bluetooth: Add LE flow control discipline")
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Changes since the standalone security submission:
- Wrap test notes to fix the GitLint B1 failures in series 1186119.
- Refresh onto bluetooth-next ff8b09806b7b without a source delta.
- Include this prerequisite as patch 1/2 of the credit RFC v3 series.
This security fix is independently useful. It does not accept identifier
zero and can be considered without patch 2. The series uses an RFC prefix
because patch 2 still requires agreement on a specification exception.
Do not queue the dependent patch alone before this prerequisite lands.
The saved standalone CI report lists every job except GitLint passing,
including the native L2CAP tester. This is not a CI result for this series.
Earlier local runs on 397464709a20: nine focused security controls pass
on security-only and combined guests. The 14 public credit controls pass
13/14 security-only (expected positive zero-ID failure), 14/14 combined.
There were no skips or captured kernel alerts in these focused runs.
GCC W=1 changed objects and source-extracted fixtures also passed there.
That base's full local attempt was incomplete: SCI Fast Mode timed out
after an invalid HCI response length for opcode 0x20a3. The same failure
reproduced unpatched; this patch does not claim to fix it. Initial spaced
VM filters selected broader tests; corrected space-free focused runs are
the results above. Historical older-base results of 133/134 and 134/134
are not fresh full-suite results for this series.
The combined Arch trial is reported working, not isolated security or
exhaustive lifetime coverage. No severity/CVE claim is made. The private
reproducer and detailed private regression logs remain excluded.
net/bluetooth/l2cap_core.c | 33 +++++++++++++++++++++++++++++++--
net/bluetooth/l2cap_sock.c | 9 +++++++--
2 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4dd56e007..7a7f30531 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5391,6 +5391,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
l2cap_chan_lock(chan);
+ if (chan->state != BT_CONNECTED ||
+ (chan->mode != L2CAP_MODE_LE_FLOWCTL &&
+ chan->mode != L2CAP_MODE_EXT_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5404,6 +5409,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->tx_credits += credits;
+ if (test_bit(FLAG_PENDING_SECURITY, &chan->flags))
+ goto unlock;
+
/* Resume sending */
l2cap_le_flowctl_send(chan);
@@ -7967,6 +7975,8 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
mutex_lock(&conn->lock);
list_for_each_entry(chan, &conn->chan_l, list) {
+ bool pending_le;
+
l2cap_chan_lock(chan);
lockdep_assert_held(&chan->conn->lock);
@@ -7974,7 +7984,12 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
state_to_string(chan->state));
- if (!status && encrypt)
+ pending_le = hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL) &&
+ test_bit(FLAG_PENDING_SECURITY, &chan->flags);
+
+ if (!status && encrypt && !pending_le)
chan->sec_level = hcon->sec_level;
if (!__l2cap_no_conn_pending(chan)) {
@@ -7984,7 +7999,21 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) {
- chan->ops->resume(chan);
+ if (pending_le) {
+ if (!encrypt ||
+ !smp_sufficient_security(hcon, chan->sec_level,
+ SMP_ALLOW_STK)) {
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
+ clear_bit(FLAG_PENDING_SECURITY, &chan->flags);
+ chan->sec_level = hcon->sec_level;
+ l2cap_le_flowctl_send(chan);
+ }
+
+ if (!pending_le || chan->tx_credits)
+ chan->ops->resume(chan);
l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c396987c5..2d7f2935c 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -993,10 +993,15 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
} else if ((sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
sk->sk_state == BT_CONNECTED) {
- if (!l2cap_chan_check_security(chan, true))
+ if (!l2cap_chan_check_security(chan, true)) {
+ if (conn->hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL))
+ set_bit(FLAG_PENDING_SECURITY, &chan->flags);
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
- else
+ } else {
sk->sk_state_change(sk);
+ }
} else {
err = -EINVAL;
}
base-commit: ff8b09806b7b18884ad8d3a2b3d702da534a4e21
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC PATCH v3 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
@ 2026-10-15 18:17 ` Kyle Pepper
2026-10-15 20:17 ` [RFC,v3,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-10-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Johan Hedberg,
linux-kernel
Tolerate exact-size, nonzero credit grants with identifier zero only
for connected LE credit-based channels. Keep the target and pending
security checks shared with ordinary identifiers. Do not send a
response with identifier zero or relax other signaling commands.
This is an interoperability exception to Core Vol 3 Part A section 4,
not a conformance fix.
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Changes since v2:
- Include the unchanged security prerequisite as patch 1/2 in this series,
rather than relying on CI to apply a separately submitted dependency.
- Refresh onto bluetooth-next ff8b09806b7b without a source delta.
- Wrap test notes to keep all prose within GitLint's 80-column limit.
The saved v2 report failed application at l2cap_core.c:5396. That patch
depends on the security fix, which was not yet upstream. A dependency
link and prerequisite-patch-id did not make that CI run apply it first.
Apply this entire series in order; patch 2 alone is not a valid input.
The Core specification still forbids identifier zero. This remains an
interoperability RFC requiring maintainer policy agreement, not a
conformance fix. Patch 1 is independently useful without this exception.
Earlier 397464709a20 runs passed all nine focused security controls with
security-only and combined guests. Public credit controls passed 13/14
security-only (expected positive zero-ID failure), 14/14 combined, with
no skips or captured kernel alerts. Source-extracted fixtures and GCC
W=1 changed objects passed. These are prior runs, not fresh v3 VMs.
The earlier full-suite attempt was incomplete due to an SCI timeout also
seen on the unpatched base. No fresh full-suite or remote CI pass is
claimed for v3. The combined Arch trial is reported working on hardware,
not isolated attribution or exhaustive device/security/teardown coverage.
Private security reproducer/logs and the archived BlueZ test companion
are excluded. This series contains only the two kernel patches.
net/bluetooth/l2cap_core.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7a7f30531..d805b1c62 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5396,6 +5396,10 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->mode != L2CAP_MODE_EXT_FLOWCTL))
goto unlock;
+ /* Tolerate identifier-zero credits only for a live LE CoC. */
+ if (!cmd->ident && (!credits || chan->mode != L2CAP_MODE_LE_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5994,11 +5998,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
- if (len != skb->len || !cmd->ident) {
+ if (len != skb->len) {
BT_DBG("corrupted command");
goto drop;
}
+ if (!cmd->ident) {
+ if (cmd->code != L2CAP_LE_CREDITS ||
+ len != sizeof(struct l2cap_le_credits))
+ goto drop;
+
+ /* Credits have no response or identifier-matched transaction. */
+ l2cap_le_credits(conn, cmd, len, skb->data);
+ goto drop;
+ }
+
err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-10-13 14:43 ` [RFC PATCH] " Luiz Augusto von Dentz
@ 2026-10-15 18:31 ` cochcoder
0 siblings, 0 replies; 15+ messages in thread
From: cochcoder @ 2026-10-15 18:31 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Marcel Holtmann, linux-kernel
Thanks for flagging this. I've sent v3 as a two-patch series:
the security fix first, followed by the dependent zero-ID RFC.
Security fix:
https://lore.kernel.org/r/20261015181624.48318-1-cochcoder@proton.me
Zero-ID RFC:
https://lore.kernel.org/r/20261015181624.48318-2-cochcoder@proton.me
Thanks,
Kyle
On Tuesday, October 13th, 2026 at 10:44 AM, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Kyle,
>
> On Mon, Oct 12, 2026 at 11:20 PM Kyle Pepper <cochcoder@proton.me> wrote:
> >
> > A nonconforming ASHA peer sends identifier-zero credit indications
> > that are discarded, reducing usable transmit credits until audio stalls.
> >
> > Tolerate only exact-size credit indications for a connected LE CoC.
> > Preserve the channel reference, lock and credit-overflow checks and do
> > not send a response with identifier zero. Other zero-ID commands and
> > BR/EDR signaling remain unchanged.
> >
> > Core Vol 3 Part A section 4 forbids identifier zero. This is an
> > interoperability RFC requiring maintainer agreement, not a conformance
> > fix or a claim of automatic stream recovery.
> >
> > Assisted-by: OpenCode:gpt-6.1-sol
> > Signed-off-by: Kyle Pepper <cochcoder@proton.me>
> > ---
> > Submission review notes (not part of the commit message):
> > Core specification forbids identifier zero. This is a narrow opcode
> > interoperability exception, not a conformance fix. N8 captures contain
> > zero-ID credit indications. Native malformed/overflow/teardown and
> > lockdep/KASAN coverage and exception policy remain review gates.
> >
> > net/bluetooth/l2cap_core.c | 18 +++++++++++++++++-
> > 1 file changed, 17 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 49a998804..1a0868437 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -5328,6 +5328,12 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
> >
> > l2cap_chan_lock(chan);
> >
> > + /* Tolerate identifier-zero credits only for a live LE CoC. */
> > + if (!cmd->ident &&
> > + (!credits || chan->state != BT_CONNECTED ||
> > + chan->mode != L2CAP_MODE_LE_FLOWCTL))
> > + goto unlock;
> > +
> > max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
> > if (credits > max_credits) {
> > BT_ERR("LE credits overflow");
> > @@ -5923,11 +5929,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
> >
> > BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
> >
> > - if (len != skb->len || !cmd->ident) {
> > + if (len != skb->len) {
> > BT_DBG("corrupted command");
> > goto drop;
> > }
> >
> > + if (!cmd->ident) {
> > + if (cmd->code != L2CAP_LE_CREDITS ||
> > + len != sizeof(struct l2cap_le_credits))
> > + goto drop;
> > +
> > + /* Credits have no response or identifier-matched transaction. */
> > + l2cap_le_credits(conn, cmd, len, skb->data);
> > + goto drop;
> > + }
> > +
> > err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
> > if (err) {
> > struct l2cap_cmd_rej_unk rej;
> >
> > base-commit: 964430c038967fd06643e866f68115664e1a1bd1
>
> Sashiko flagged a problem with this:
>
> https://sashiko.dev/#/patchset/20261013031943.489829-1-cochcoder%40proton.me
>
> --
> Luiz Augusto von Dentz
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [RFC,v3,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
2026-10-15 18:17 ` [RFC PATCH v3 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
@ 2026-10-15 20:17 ` bluez.test.bot
2026-10-31 18:09 ` [RFC PATCH v3 1/2] " cochcoder
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
3 siblings, 0 replies; 15+ messages in thread
From: bluez.test.bot @ 2026-10-15 20:17 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 1073 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1186712/
---Test result---
Test Summary:
CheckPatch PASS 1.74 seconds
VerifyFixes PASS 0.12 seconds
VerifySignedoff PASS 0.12 seconds
GitLint PASS 0.64 seconds
SubjectPrefix PASS 0.23 seconds
BuildKernel PASS 31.51 seconds
CheckAllWarning PASS 33.73 seconds
CheckSparse PASS 36.47 seconds
BuildKernel32 PASS 29.38 seconds
CheckKernelLLVM PASS 35.28 seconds
TestRunnerSetup PASS 702.28 seconds
TestRunner_l2cap-tester PASS 12.79 seconds
IncrementalBuild PASS 31.19 seconds
https://github.com/bluez/bluetooth-next/pull/952
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
2026-10-15 18:17 ` [RFC PATCH v3 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-10-15 20:17 ` [RFC,v3,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
@ 2026-10-31 18:09 ` cochcoder
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
3 siblings, 0 replies; 15+ messages in thread
From: cochcoder @ 2026-10-31 18:09 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Johan Hedberg,
linux-kernel
Hi,
Following up on this patch, is there anything else needed to move it forward?
Thanks,
Kyle
On Thursday, October 15th, 2026 at 2:16 PM, Kyle Pepper <cochcoder@proton.me> wrote:
> Credit indications can invoke resume on fixed or unready channels.
> Connected LE credit-based sockets can also resume during a security
> upgrade because credits and security share the socket suspend flag.
>
> Validate the target mode and state for every identifier. Track pending
> LE/ECRED security upgrades and retain credits without sending queued
> data or resuming the socket until encryption meets the requested level.
> Drain queued data after security completes and keep credit-starved
> sockets suspended.
>
> Fixes: fad5fc89594d ("Bluetooth: Add LE flow control discipline")
> Assisted-by: OpenCode:gpt-6.1-sol
> Signed-off-by: Kyle Pepper <cochcoder@proton.me>
> ---
> Changes since the standalone security submission:
> - Wrap test notes to fix the GitLint B1 failures in series 1186119.
> - Refresh onto bluetooth-next ff8b09806b7b without a source delta.
> - Include this prerequisite as patch 1/2 of the credit RFC v3 series.
>
> This security fix is independently useful. It does not accept identifier
> zero and can be considered without patch 2. The series uses an RFC prefix
> because patch 2 still requires agreement on a specification exception.
> Do not queue the dependent patch alone before this prerequisite lands.
>
> The saved standalone CI report lists every job except GitLint passing,
> including the native L2CAP tester. This is not a CI result for this series.
>
> Earlier local runs on 397464709a20: nine focused security controls pass
> on security-only and combined guests. The 14 public credit controls pass
> 13/14 security-only (expected positive zero-ID failure), 14/14 combined.
> There were no skips or captured kernel alerts in these focused runs.
> GCC W=1 changed objects and source-extracted fixtures also passed there.
>
> That base's full local attempt was incomplete: SCI Fast Mode timed out
> after an invalid HCI response length for opcode 0x20a3. The same failure
> reproduced unpatched; this patch does not claim to fix it. Initial spaced
> VM filters selected broader tests; corrected space-free focused runs are
> the results above. Historical older-base results of 133/134 and 134/134
> are not fresh full-suite results for this series.
>
> The combined Arch trial is reported working, not isolated security or
> exhaustive lifetime coverage. No severity/CVE claim is made. The private
> reproducer and detailed private regression logs remain excluded.
>
> net/bluetooth/l2cap_core.c | 33 +++++++++++++++++++++++++++++++--
> net/bluetooth/l2cap_sock.c | 9 +++++++--
> 2 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 4dd56e007..7a7f30531 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -5391,6 +5391,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
>
> l2cap_chan_lock(chan);
>
> + if (chan->state != BT_CONNECTED ||
> + (chan->mode != L2CAP_MODE_LE_FLOWCTL &&
> + chan->mode != L2CAP_MODE_EXT_FLOWCTL))
> + goto unlock;
> +
> max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
> if (credits > max_credits) {
> BT_ERR("LE credits overflow");
> @@ -5404,6 +5409,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
>
> chan->tx_credits += credits;
>
> + if (test_bit(FLAG_PENDING_SECURITY, &chan->flags))
> + goto unlock;
> +
> /* Resume sending */
> l2cap_le_flowctl_send(chan);
>
> @@ -7967,6 +7975,8 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> mutex_lock(&conn->lock);
>
> list_for_each_entry(chan, &conn->chan_l, list) {
> + bool pending_le;
> +
> l2cap_chan_lock(chan);
>
> lockdep_assert_held(&chan->conn->lock);
> @@ -7974,7 +7984,12 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
> state_to_string(chan->state));
>
> - if (!status && encrypt)
> + pending_le = hcon->type == LE_LINK &&
> + (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
> + chan->mode == L2CAP_MODE_EXT_FLOWCTL) &&
> + test_bit(FLAG_PENDING_SECURITY, &chan->flags);
> +
> + if (!status && encrypt && !pending_le)
> chan->sec_level = hcon->sec_level;
>
> if (!__l2cap_no_conn_pending(chan)) {
> @@ -7984,7 +7999,21 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
>
> if (!status && (chan->state == BT_CONNECTED ||
> chan->state == BT_CONFIG)) {
> - chan->ops->resume(chan);
> + if (pending_le) {
> + if (!encrypt ||
> + !smp_sufficient_security(hcon, chan->sec_level,
> + SMP_ALLOW_STK)) {
> + l2cap_chan_unlock(chan);
> + continue;
> + }
> +
> + clear_bit(FLAG_PENDING_SECURITY, &chan->flags);
> + chan->sec_level = hcon->sec_level;
> + l2cap_le_flowctl_send(chan);
> + }
> +
> + if (!pending_le || chan->tx_credits)
> + chan->ops->resume(chan);
> l2cap_check_encryption(chan, encrypt);
> l2cap_chan_unlock(chan);
> continue;
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index c396987c5..2d7f2935c 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -993,10 +993,15 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
> } else if ((sk->sk_state == BT_CONNECT2 &&
> test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
> sk->sk_state == BT_CONNECTED) {
> - if (!l2cap_chan_check_security(chan, true))
> + if (!l2cap_chan_check_security(chan, true)) {
> + if (conn->hcon->type == LE_LINK &&
> + (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
> + chan->mode == L2CAP_MODE_EXT_FLOWCTL))
> + set_bit(FLAG_PENDING_SECURITY, &chan->flags);
> set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
> - else
> + } else {
> sk->sk_state_change(sk);
> + }
> } else {
> err = -EINVAL;
> }
>
> base-commit: ff8b09806b7b18884ad8d3a2b3d702da534a4e21
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH v4 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
` (2 preceding siblings ...)
2026-10-31 18:09 ` [RFC PATCH v3 1/2] " cochcoder
@ 2026-11-06 2:17 ` Kyle Pepper
2026-11-06 2:18 ` [RFC PATCH v4 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
` (2 more replies)
3 siblings, 3 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-11-06 2:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: luiz.dentz, marcel
Validate credit targets and retain credits without sending or resuming
while an LE or ECRED security upgrade is pending. Keep the requested
security level until encryption and key size satisfy it.
Schedule immediate channel timeout work if the upgrade fails. This runs
the normal close path outside the security callback list traversal and
keeps traffic suspended until teardown. Complete deferred security
without accepting the connection or sending queued data.
Drain connected channels after successful security completion. Resume
LE credit-based sockets only when credits remain, including background
encryption changes with no locally pending upgrade.
Fixes: fad5fc89594d ("Bluetooth: Add LE flow control discipline")
Assisted-by: LLM
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
v4: Fix failed/deferred security completion and credit-aware wakeups.
AI review: https://sashiko.dev/#/patchset/20261015181624.48318-1-cochcoder%40proton.me
net/bluetooth/l2cap_core.c | 50 ++++++++++++++++++++++++++++++++++++--
net/bluetooth/l2cap_sock.c | 9 +++++--
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7dcb0586a..9463ac215 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5380,6 +5380,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
l2cap_chan_lock(chan);
+ if (chan->state != BT_CONNECTED ||
+ (chan->mode != L2CAP_MODE_LE_FLOWCTL &&
+ chan->mode != L2CAP_MODE_EXT_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5393,6 +5398,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->tx_credits += credits;
+ if (test_bit(FLAG_PENDING_SECURITY, &chan->flags))
+ goto unlock;
+
/* Resume sending */
l2cap_le_flowctl_send(chan);
@@ -7976,6 +7984,8 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
mutex_lock(&conn->lock);
list_for_each_entry(chan, &conn->chan_l, list) {
+ bool le_flowctl, pending_le;
+
l2cap_chan_lock(chan);
lockdep_assert_held(&chan->conn->lock);
@@ -7983,7 +7993,13 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
state_to_string(chan->state));
- if (!status && encrypt)
+ le_flowctl = hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL);
+ pending_le = le_flowctl &&
+ test_bit(FLAG_PENDING_SECURITY, &chan->flags);
+
+ if (!status && encrypt && !pending_le)
chan->sec_level = hcon->sec_level;
if (!__l2cap_no_conn_pending(chan)) {
@@ -7991,9 +8007,39 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
continue;
}
+ if (pending_le && (chan->state == BT_CONNECTED ||
+ chan->state == BT_CONFIG ||
+ chan->state == BT_CONNECT2)) {
+ if (status || !encrypt ||
+ !smp_sufficient_security(hcon, chan->sec_level,
+ SMP_ALLOW_STK) ||
+ !l2cap_check_enc_key_size(hcon, chan)) {
+ /* Keep traffic suspended until timeout work closes
+ * the channel outside this list traversal.
+ */
+ __set_chan_timer(chan, 0);
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
+ clear_bit(FLAG_PENDING_SECURITY, &chan->flags);
+ chan->sec_level = hcon->sec_level;
+
+ /* Security completion must not accept deferred setup. */
+ if (chan->state == BT_CONNECT2) {
+ if (chan->tx_credits)
+ chan->ops->resume(chan);
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
+ l2cap_le_flowctl_send(chan);
+ }
+
if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) {
- chan->ops->resume(chan);
+ if (!le_flowctl || chan->tx_credits)
+ chan->ops->resume(chan);
l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 7a2551ef7..2cf91d0a0 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -993,10 +993,15 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
} else if ((sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
sk->sk_state == BT_CONNECTED) {
- if (!l2cap_chan_check_security(chan, true))
+ if (!l2cap_chan_check_security(chan, true)) {
+ if (conn->hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL))
+ set_bit(FLAG_PENDING_SECURITY, &chan->flags);
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
- else
+ } else {
sk->sk_state_change(sk);
+ }
} else {
err = -EINVAL;
}
base-commit: a063a00e6cd9e354aa6d67a154a0527951d7f881
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC PATCH v4 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
@ 2026-11-06 2:18 ` Kyle Pepper
2026-11-06 3:17 ` [RFC,v4,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
2026-11-06 4:55 ` [RFC PATCH v5 1/2] " Kyle Pepper
2 siblings, 0 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-11-06 2:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: luiz.dentz, marcel
Keep the narrow identifier-zero exception for nonzero credit grants to
connected LE CoC channels. Apply the same mode, state and pending
security checks as ordinary credit indications.
This interoperability exception depends on the security fix and still
requires maintainer policy approval.
Assisted-by: LLM
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
No code change; depends on patch 1. Maintainer policy approval remains required.
AI review: https://sashiko.dev/#/patchset/20261015181624.48318-1-cochcoder%40proton.me
net/bluetooth/l2cap_core.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9463ac215..4bef75235 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5385,6 +5385,10 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->mode != L2CAP_MODE_EXT_FLOWCTL))
goto unlock;
+ /* Tolerate identifier-zero credits only for a live LE CoC. */
+ if (!cmd->ident && (!credits || chan->mode != L2CAP_MODE_LE_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5994,11 +5998,21 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
- if (len != skb->len || !cmd->ident) {
+ if (len != skb->len) {
BT_DBG("corrupted command");
goto drop;
}
+ if (!cmd->ident) {
+ if (cmd->code != L2CAP_LE_CREDITS ||
+ len != sizeof(struct l2cap_le_credits))
+ goto drop;
+
+ /* Credits have no response or identifier-matched transaction. */
+ l2cap_le_credits(conn, cmd, len, skb->data);
+ goto drop;
+ }
+
err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* RE: [RFC,v4,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
2026-11-06 2:18 ` [RFC PATCH v4 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
@ 2026-11-06 3:17 ` bluez.test.bot
2026-11-06 4:55 ` [RFC PATCH v5 1/2] " Kyle Pepper
2 siblings, 0 replies; 15+ messages in thread
From: bluez.test.bot @ 2026-11-06 3:17 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 4202 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1203684/
---Test result---
Test Summary:
CheckPatch FAIL 1.20 seconds
VerifyFixes PASS 0.12 seconds
VerifySignedoff PASS 0.07 seconds
GitLint PASS 0.45 seconds
SubjectPrefix PASS 0.12 seconds
BuildKernel PASS 24.36 seconds
CheckAllWarning PASS 32.27 seconds
CheckSparse PASS 30.88 seconds
BuildKernel32 PASS 24.22 seconds
CheckKernelLLVM PASS 25.68 seconds
TestRunnerSetup PASS 558.75 seconds
TestRunner_l2cap-tester FAIL 11.79 seconds
IncrementalBuild PASS 28.69 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[RFC,v4,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
WARNING: Non-standard signature: Assisted-by:
#99:
Assisted-by: LLM
ERROR: Unrecognized email address: 'LLM'
#99:
Assisted-by: LLM
total: 1 errors, 1 warnings, 0 checks, 99 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/home/runner/work/bluetooth-next/bluetooth-next/src/patch/14955882.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[RFC,v4,2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
WARNING: Non-standard signature: Assisted-by:
#93:
Assisted-by: LLM
ERROR: Unrecognized email address: 'LLM'
#93:
Assisted-by: LLM
total: 1 errors, 1 warnings, 0 checks, 32 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/home/runner/work/bluetooth-next/bluetooth-next/src/patch/14955883.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Sanitizer errors:
==35==ERROR: AddressSanitizer: heap-use-after-free on address 0x7b8639ae33d0 at pc 0x5583cbda5eee bp 0x7ffd73a0c830 sp 0x7ffd73a0c820
READ of size 4 at 0x7b8639ae33d0 thread T0
#0 0x5583cbda5eed in timeout_callback src/shared/timeout-mainloop.c:33
#1 0x5583cbda6ed5 in timeout_callback src/shared/mainloop.c:271
#2 0x5583cbda8006 in mainloop_run src/shared/mainloop.c:125
#3 0x5583cbdaa96a in mainloop_run_with_signal src/shared/mainloop-notify.c:196
#4 0x5583cbdafc4b in tester_run src/shared/tester.c:1297
#5 0x5583cbcd91dd in main tools/l2cap-tester.c:3918
#6 0x7f463aa34600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59
#7 0x7f463aa34717 in __libc_start_main_impl ../csu/libc-start.c:360
#8 0x5583cbcdfce4 in _start (/home/runner/work/bluetooth-next/bluetooth-next/src/bluez/tools/l2cap-tester+0x16dce4) (BuildId: 0d2067a7ef8fe61fcf622598953c7d0f996221a0)
0x7b8639ae33d0 is located 0 bytes inside of 40-byte region [0x7b8639ae33d0,0x7b8639ae33f8)
freed by thread T0 here:
#0 0x7f463b3723ff in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:51
#1 0x5583cbda63ca in timeout_destroy src/shared/mainloop.c:252
previously allocated by thread T0 here:
#0 0x7f463b37360f in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:67
#1 0x5583cbd90335 in util_malloc src/shared/util.c:46
SUMMARY: AddressSanitizer: heap-use-after-free src/shared/timeout-mainloop.c:33 in timeout_callback
No test result found
https://github.com/bluez/bluetooth-next/pull/1075
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH v5 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
2026-11-06 2:18 ` [RFC PATCH v4 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-11-06 3:17 ` [RFC,v4,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
@ 2026-11-06 4:55 ` Kyle Pepper
2026-11-06 4:56 ` [RFC PATCH v5 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2 siblings, 1 reply; 15+ messages in thread
From: Kyle Pepper @ 2026-11-06 4:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: luiz.dentz, marcel
Retain LE and ECRED credits without sending or resuming sockets while a
security upgrade is pending. Check the shared send path so a send that
crossed socket readiness or allocation lock gaps cannot drain queued
data at the old security level.
Reject deferred acceptance with EAGAIN while security is pending. Keep
the requested level unchanged and return EBUSY for another BT_SECURITY
request until completion or teardown, including the interval before
failed-upgrade timeout work closes the channel.
Validate encryption and key size before completing security, preserve
deferred setup, and resume connected sockets only when credits remain.
Schedule failed-upgrade teardown outside the channel-list traversal.
Assisted-by: LLM
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Changes in v5:
- Guard the shared send path across socket and allocation lock gaps.
- Keep deferred acceptance blocked while security is pending.
- Reject another BT_SECURITY request until completion or teardown.
AI review:
https://sashiko.dev/#/patchset/20261106021723.631339-1-cochcoder%40proton.me
GCC/Clang sanitizer fixtures, negative controls and W=1 object builds pass.
The local full kernel image builds with KASAN and lockdep enabled.
Native L2CAP and hardware behavior remain unverified. PR1075's BlueZ timeout
use-after-free and checkpatch attribution compatibility need separate CI fixes.
AI assistance: Codex prepared source revisions, descriptions and local tests
in response to the v4 automated review. Attribution is retained.
net/bluetooth/l2cap_core.c | 53 ++++++++++++++++++++++++++++++++++++--
net/bluetooth/l2cap_sock.c | 22 ++++++++++++++--
2 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7dcb0586a..ae6659fab 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2647,6 +2647,9 @@ static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
BT_DBG("chan %p", chan);
+ if (test_bit(FLAG_PENDING_SECURITY, &chan->flags))
+ return;
+
while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
chan->tx_credits--;
@@ -5380,6 +5383,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
l2cap_chan_lock(chan);
+ if (chan->state != BT_CONNECTED ||
+ (chan->mode != L2CAP_MODE_LE_FLOWCTL &&
+ chan->mode != L2CAP_MODE_EXT_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5393,6 +5401,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->tx_credits += credits;
+ if (test_bit(FLAG_PENDING_SECURITY, &chan->flags))
+ goto unlock;
+
/* Resume sending */
l2cap_le_flowctl_send(chan);
@@ -7976,6 +7987,8 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
mutex_lock(&conn->lock);
list_for_each_entry(chan, &conn->chan_l, list) {
+ bool le_flowctl, pending_le;
+
l2cap_chan_lock(chan);
lockdep_assert_held(&chan->conn->lock);
@@ -7983,7 +7996,13 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
state_to_string(chan->state));
- if (!status && encrypt)
+ le_flowctl = hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL);
+ pending_le = le_flowctl &&
+ test_bit(FLAG_PENDING_SECURITY, &chan->flags);
+
+ if (!status && encrypt && !pending_le)
chan->sec_level = hcon->sec_level;
if (!__l2cap_no_conn_pending(chan)) {
@@ -7991,9 +8010,39 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
continue;
}
+ if (pending_le && (chan->state == BT_CONNECTED ||
+ chan->state == BT_CONFIG ||
+ chan->state == BT_CONNECT2)) {
+ if (status || !encrypt ||
+ !smp_sufficient_security(hcon, chan->sec_level,
+ SMP_ALLOW_STK) ||
+ !l2cap_check_enc_key_size(hcon, chan)) {
+ /* Keep traffic suspended until timeout work closes
+ * the channel outside this list traversal.
+ */
+ __set_chan_timer(chan, 0);
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
+ clear_bit(FLAG_PENDING_SECURITY, &chan->flags);
+ chan->sec_level = hcon->sec_level;
+
+ /* Security completion must not accept deferred setup. */
+ if (chan->state == BT_CONNECT2) {
+ if (chan->tx_credits)
+ chan->ops->resume(chan);
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
+ l2cap_le_flowctl_send(chan);
+ }
+
if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) {
- chan->ops->resume(chan);
+ if (!le_flowctl || chan->tx_credits)
+ chan->ops->resume(chan);
l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 7a2551ef7..cc00ef688 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -972,6 +972,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
+ /* Preserve an outstanding LE credit-based security request. */
+ if ((chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL) &&
+ test_bit(FLAG_PENDING_SECURITY, &chan->flags)) {
+ err = -EBUSY;
+ break;
+ }
+
chan->sec_level = sec.level;
conn = l2cap_chan_conn(chan);
@@ -993,10 +1001,15 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
} else if ((sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
sk->sk_state == BT_CONNECTED) {
- if (!l2cap_chan_check_security(chan, true))
+ if (!l2cap_chan_check_security(chan, true)) {
+ if (conn->hcon->type == LE_LINK &&
+ (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL))
+ set_bit(FLAG_PENDING_SECURITY, &chan->flags);
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
- else
+ } else {
sk->sk_state_change(sk);
+ }
} else {
err = -EINVAL;
}
@@ -1263,6 +1276,11 @@ static int l2cap_sock_defer(struct sock *sk)
if (!have_conn) {
release_sock(sk);
err = -ENOTCONN;
+ } else if ((chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+ chan->mode == L2CAP_MODE_EXT_FLOWCTL) &&
+ test_bit(FLAG_PENDING_SECURITY, &chan->flags)) {
+ release_sock(sk);
+ err = -EAGAIN;
} else if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
sk->sk_state = BT_CONNECTED;
chan->state = BT_CONNECTED;
base-commit: a063a00e6cd9e354aa6d67a154a0527951d7f881
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC PATCH v5 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications
2026-11-06 4:55 ` [RFC PATCH v5 1/2] " Kyle Pepper
@ 2026-11-06 4:56 ` Kyle Pepper
0 siblings, 0 replies; 15+ messages in thread
From: Kyle Pepper @ 2026-11-06 4:56 UTC (permalink / raw)
To: linux-bluetooth; +Cc: luiz.dentz, marcel
Cochlear Nucleus N8 captures contain LE credit indications with
identifier zero. The specification forbids zero identifiers, so the
current parser discards these grants and leaves the channel without
usable transmit credits.
Accept nonzero grants only for connected legacy LE CoC channels. Keep
ECRED and all other commands excluded because the observed
interoperability issue concerns legacy LE CoC. Apply normal credit
overflow and pending-security handling, including the shared transmit
guard from the preceding patch.
Let the credit handler validate the exact payload size after the
signaling parser validates framing.
Assisted-by: LLM
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Changes in v5:
- Explain the observed Nucleus N8 behavior and legacy LE CoC restriction.
- Use the credit handler's existing exact payload-size validation.
- Depend on v5's shared security transmit guard.
AI review:
https://sashiko.dev/#/patchset/20261106021723.631339-1-cochcoder%40proton.me
Credit/parser fixtures pass. ECRED remains excluded from the zero-ID exception.
Native L2CAP and hardware behavior remain unverified. The interoperability
exception remains subject to maintainer policy approval.
AI assistance: Codex prepared source revisions, descriptions and local tests
in response to the v4 automated review. Attribution is retained.
net/bluetooth/l2cap_core.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ae6659fab..d3b875c47 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5388,6 +5388,10 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
chan->mode != L2CAP_MODE_EXT_FLOWCTL))
goto unlock;
+ /* Tolerate identifier-zero credits only for a live LE CoC. */
+ if (!cmd->ident && (!credits || chan->mode != L2CAP_MODE_LE_FLOWCTL))
+ goto unlock;
+
max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
if (credits > max_credits) {
BT_ERR("LE credits overflow");
@@ -5997,11 +6001,20 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
- if (len != skb->len || !cmd->ident) {
+ if (len != skb->len) {
BT_DBG("corrupted command");
goto drop;
}
+ if (!cmd->ident) {
+ if (cmd->code != L2CAP_LE_CREDITS)
+ goto drop;
+
+ /* Credits have no response or identifier-matched transaction. */
+ l2cap_le_credits(conn, cmd, len, skb->data);
+ goto drop;
+ }
+
err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-11-06 4:56 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 3:19 [RFC PATCH] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-10-13 4:20 ` [RFC] " bluez.test.bot
2026-10-13 14:43 ` [RFC PATCH] " Luiz Augusto von Dentz
2026-10-15 18:31 ` cochcoder
2026-10-15 5:28 ` [RFC PATCH v2] " Kyle Pepper
2026-10-15 6:42 ` [RFC,v2] " bluez.test.bot
2026-10-15 18:16 ` [RFC PATCH v3 1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades Kyle Pepper
2026-10-15 18:17 ` [RFC PATCH v3 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-10-15 20:17 ` [RFC,v3,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
2026-10-31 18:09 ` [RFC PATCH v3 1/2] " cochcoder
2026-11-06 2:17 ` [RFC PATCH v4 " Kyle Pepper
2026-11-06 2:18 ` [RFC PATCH v4 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
2026-11-06 3:17 ` [RFC,v4,1/2] Bluetooth: L2CAP: Keep credits from completing security upgrades bluez.test.bot
2026-11-06 4:55 ` [RFC PATCH v5 1/2] " Kyle Pepper
2026-11-06 4:56 ` [RFC PATCH v5 2/2] Bluetooth: L2CAP: tolerate zero-ident LE credit indications Kyle Pepper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox