* [PATCH v4 2/6] Bluetooth: L2CAP: Reject signalling responses in invalid states
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
@ 2026-10-13 15:36 ` Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 3/6] Bluetooth: L2CAP: Reject invalid TxWindow in configuration requests Siwei Zhang
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Siwei Zhang @ 2026-10-13 15:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
A peer can send configuration messages while an
incoming channel is in BT_CONNECT2, before the
security or deferred accept gate has completed. A
configuration response can then promote the channel
to BT_CONNECTED. Configuration responses can also
act on channels that are closing, and a late connection
response can move a disconnecting channel back to
BT_CONFIG.
Accept connection responses only while waiting in
BT_CONNECT. Answer configuration requests in
BT_CONNECT2, but defer our own request until
BT_CONFIG so configuration cannot complete before
the gate. Ignore configuration responses outside
BT_CONFIG and BT_CONNECTED, and only complete
configuration in BT_CONFIG.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
v4:
- default l2cap_conf_rfc.mode to chan->mode
v3: https://lore.kernel.org/linux-bluetooth/20261007144717.3832330-1-oss@fourdim.xyz/
- git lint on comments
v2: https://lore.kernel.org/linux-bluetooth/20260929154219.2366060-1-oss@fourdim.xyz/
- resolve the patch conflict
v1: https://lore.kernel.org/linux-bluetooth/20260928173324.1837653-1-oss@fourdim.xyz/
net/bluetooth/l2cap_core.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c730da87734b..eb55c16760a7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4442,6 +4442,10 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
lockdep_assert_held(&chan->conn->lock);
+ /* Ignore a late response after the channel has left BT_CONNECT. */
+ if (chan->state != BT_CONNECT)
+ goto done;
+
switch (result) {
case L2CAP_CR_SUCCESS:
if (__l2cap_get_chan_by_dcid(conn, dcid)) {
@@ -4471,6 +4475,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
break;
}
+done:
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
@@ -4608,7 +4613,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
goto unlock;
}
- if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
+ /* A channel in BT_CONNECT2 has not passed security or userspace
+ * accept yet. Answer the peer's request, but hold our own until
+ * the channel reaches BT_CONFIG: the CONNECT2 -> CONFIG sites send
+ * it. Connected channels may also need to reconfigure.
+ */
+ if ((chan->state == BT_CONFIG || chan->state == BT_CONNECTED) &&
+ !test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
u8 buf[64];
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
@@ -4661,6 +4672,10 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
lockdep_assert_held(&chan->conn->lock);
+ /* Connected channels may also receive reconfiguration responses. */
+ if (chan->state != BT_CONFIG && chan->state != BT_CONNECTED)
+ goto done;
+
switch (result) {
case L2CAP_CONF_SUCCESS:
l2cap_conf_rfc_get(chan, rsp->data, len);
@@ -4728,6 +4743,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
set_default_fcs(chan);
+ if (chan->state != BT_CONFIG)
+ goto done;
+
if (chan->mode == L2CAP_MODE_ERTM ||
chan->mode == L2CAP_MODE_STREAMING)
err = l2cap_ertm_init(chan);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 3/6] Bluetooth: L2CAP: Reject invalid TxWindow in configuration requests
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 2/6] Bluetooth: L2CAP: Reject signalling responses in invalid states Siwei Zhang
@ 2026-10-13 15:36 ` Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 4/6] Bluetooth: L2CAP: Use default TxWindow for zero socket option Siwei Zhang
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Siwei Zhang @ 2026-10-13 15:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
A peer can send an ERTM RFC option with a TxWindow
of zero, which is out of spec. It is stored in
remote_tx_win unchanged and later passed to
l2cap_seq_list_init(), where roundup_pow_of_two(0)
is undefined. On some architectures this results in
a ZERO_SIZE_PTR list and a remote kernel oops.
A TxWindow above 63 is out of spec as well. With
6-bit sequence numbers we would then send more
unacknowledged frames than the sequence space can
tell apart.
Reply with L2CAP_CONF_UNACCEPT and propose the
default TxWindow instead of accepting the value, so
remote_tx_win always stays within 1 to 63. Keep the
parameters of an earlier request then, and do not
treat the request as done because an earlier one was.
Also refuse a zero size in l2cap_seq_list_init(), so
any other path that reaches it with a zero TxWindow
fails the channel instead of the kernel.
Fixes: f2fcfcd67025 ("Bluetooth: Add configuration support for ERTM and Streaming mode")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
net/bluetooth/l2cap_core.c | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index eb55c16760a7..7ea13c0fad44 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -321,6 +321,10 @@ static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
{
size_t alloc_size, i;
+ /* roundup_pow_of_two(0) is undefined */
+ if (!size)
+ return -EINVAL;
+
/* Allocated size is a power of 2 to map sequence numbers
* (which may be up to 14 bits) in to a smaller array that is
* sized for the negotiated ERTM transmit windows.
@@ -3723,18 +3727,33 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
break;
case L2CAP_MODE_ERTM:
- if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
- chan->remote_tx_win = rfc.txwin_size;
- else
- rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
-
- chan->remote_max_tx = rfc.max_transmit;
-
size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
rfc.max_pdu_size = cpu_to_le16(size);
- chan->remote_mps = size;
+
+ /* The TxWindow must be within 1 to 63, otherwise
+ * propose the default one and keep the parameters of
+ * an earlier request. This overrides a PENDING result
+ * from the EFS check above, so the request is no
+ * longer pending, nor done if an earlier one was.
+ */
+ if (!rfc.txwin_size ||
+ rfc.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+ result = L2CAP_CONF_UNACCEPT;
+ clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
+ clear_bit(CONF_OUTPUT_DONE, &chan->conf_state);
+ rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
+ remote_efs = 0;
+ } else {
+ if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
+ chan->remote_tx_win = rfc.txwin_size;
+ else
+ rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
+
+ chan->remote_max_tx = rfc.max_transmit;
+ chan->remote_mps = size;
+ }
__l2cap_set_ertm_timeouts(chan, &rfc);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 4/6] Bluetooth: L2CAP: Use default TxWindow for zero socket option
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 2/6] Bluetooth: L2CAP: Reject signalling responses in invalid states Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 3/6] Bluetooth: L2CAP: Reject invalid TxWindow in configuration requests Siwei Zhang
@ 2026-10-13 15:36 ` Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests Siwei Zhang
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Siwei Zhang @ 2026-10-13 15:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
L2CAP_OPTIONS accepts a txwin_size of zero and
stores it in tx_win. The zero is then sent to the
peer in our configuration request, and if the
channel ends up in ERTM mode it is passed to
l2cap_seq_list_init().
Use the default TxWindow instead, as the mode can
still be changed to ERTM during configuration.
Fixes: 14b5aa71ec50 ("Bluetooth: Add sockopt configuration for txWindow on L2CAP")
Cc: stable@vger.kernel.org
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
net/bluetooth/l2cap_sock.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c92f31b997dd..47b0f8886fd1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -815,6 +815,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break;
}
+ /* A zero TxWindow is invalid, use the default instead */
+ if (!opts.txwin_size)
+ opts.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
+
if (!l2cap_valid_mtu(chan, opts.imtu)) {
err = -EINVAL;
break;
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
` (2 preceding siblings ...)
2026-10-13 15:36 ` [PATCH v4 4/6] Bluetooth: L2CAP: Use default TxWindow for zero socket option Siwei Zhang
@ 2026-10-13 15:36 ` Siwei Zhang
2026-10-13 15:36 ` [PATCH v4 6/6] Bluetooth: L2CAP: Remove dead configuration state code Siwei Zhang
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Siwei Zhang @ 2026-10-13 15:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
An outgoing channel waits in BT_CONNECT until security
and the feature mask exchange complete, and only then
sends its connection request. A peer can answer it
before that with a connection response matching our
source CID. The channel then moves to BT_CONFIG,
completes configuration and becomes connected before
security has completed. If security then fails,
l2cap_security_cfm() leaves the connected channel
alone, so it stays up on a link that did not reach
the required security level.
A connection response with a zero source CID is
matched by identifier. Another channel can hold the
same identifier for a response it still has to send,
so the lookup can pick the wrong channel.
Only accept a connection response while our request
is outstanding, and only look at such channels when
matching by identifier.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
net/bluetooth/l2cap_core.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7ea13c0fad44..210d1507af7e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -157,6 +157,29 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
return NULL;
}
+/* Our connection request has been sent and is still outstanding */
+static bool l2cap_chan_connect_pending(struct l2cap_chan *chan)
+{
+ return chan->state == BT_CONNECT &&
+ test_bit(CONF_CONNECT_PEND, &chan->conf_state);
+}
+
+/* Other channels may hold the same ident for a response they still have
+ * to send, so only look at channels waiting for a connection response.
+ */
+static struct l2cap_chan *__l2cap_get_connect_chan_by_ident(struct l2cap_conn *conn,
+ u8 ident)
+ __must_hold(&conn->lock)
+{
+ struct l2cap_chan *c;
+
+ list_for_each_entry(c, &conn->chan_l, list) {
+ if (c->ident == ident && l2cap_chan_connect_pending(c))
+ return c;
+ }
+ return NULL;
+}
+
static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
u8 src_type)
__must_hold_shared(&chan_list_lock)
@@ -4446,7 +4469,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
if (!chan)
return -EBADSLT;
} else {
- chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
+ chan = __l2cap_get_connect_chan_by_ident(conn, cmd->ident);
if (!chan)
return -EBADSLT;
}
@@ -4461,8 +4484,11 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
lockdep_assert_held(&chan->conn->lock);
- /* Ignore a late response after the channel has left BT_CONNECT. */
- if (chan->state != BT_CONNECT)
+ /* Only accept a response to a connection request we sent and that
+ * is still outstanding. A channel waiting in BT_CONNECT for security
+ * or the feature mask has not sent one yet.
+ */
+ if (!l2cap_chan_connect_pending(chan))
goto done;
switch (result) {
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 6/6] Bluetooth: L2CAP: Remove dead configuration state code
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
` (3 preceding siblings ...)
2026-10-13 15:36 ` [PATCH v4 5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests Siwei Zhang
@ 2026-10-13 15:36 ` Siwei Zhang
2026-10-13 20:18 ` [v4,1/6] Bluetooth: L2CAP: Reject mode changes on connected channels bluez.test.bot
2026-10-14 17:20 ` [PATCH v4 1/6] " patchwork-bot+bluetooth
6 siblings, 0 replies; 8+ messages in thread
From: Siwei Zhang @ 2026-10-13 15:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
CONF_EWS_RECV has not been set since commit
e7b02296fb40 ("Bluetooth: Remove BT_HS"), which
made configuration requests with an EWS option
be refused. Remove the flag and the branch in
l2cap_parse_conf_req() that tests it.
A pending connection response no longer needs to
set CONF_CONNECT_PEND, as connection responses are
only accepted while it is already set.
No functional change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
include/net/bluetooth/l2cap.h | 1 -
net/bluetooth/l2cap_core.c | 8 ++------
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index efb9b7f422d1..54eddcdd341f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -725,7 +725,6 @@ enum {
CONF_CONNECT_PEND,
CONF_RECV_NO_FCS,
CONF_STATE2_DEVICE,
- CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
CONF_REM_CONF_PEND,
CONF_NOT_COMPLETE,
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 210d1507af7e..4dd56e0074fd 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3769,11 +3769,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
remote_efs = 0;
} else {
- if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
- chan->remote_tx_win = rfc.txwin_size;
- else
- rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
-
+ chan->remote_tx_win = rfc.txwin_size;
chan->remote_max_tx = rfc.max_transmit;
chan->remote_mps = size;
}
@@ -4512,7 +4508,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
break;
case L2CAP_CR_PEND:
- set_bit(CONF_CONNECT_PEND, &chan->conf_state);
+ /* Our request is still outstanding */
break;
default:
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* RE: [v4,1/6] Bluetooth: L2CAP: Reject mode changes on connected channels
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
` (4 preceding siblings ...)
2026-10-13 15:36 ` [PATCH v4 6/6] Bluetooth: L2CAP: Remove dead configuration state code Siwei Zhang
@ 2026-10-13 20:18 ` bluez.test.bot
2026-10-14 17:20 ` [PATCH v4 1/6] " patchwork-bot+bluetooth
6 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-10-13 20:18 UTC (permalink / raw)
To: linux-bluetooth, oss
[-- Attachment #1: Type: text/plain, Size: 1370 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/1184901/
---Test result---
Test Summary:
CheckPatch PASS 5.99 seconds
VerifyFixes PASS 0.11 seconds
VerifySignedoff PASS 0.11 seconds
GitLint FAIL 3.59 seconds
SubjectPrefix PASS 0.74 seconds
BuildKernel PASS 30.53 seconds
CheckAllWarning PASS 34.55 seconds
CheckSparse PASS 38.13 seconds
BuildKernel32 PASS 28.88 seconds
CheckKernelLLVM PASS 34.50 seconds
TestRunnerSetup PASS 667.05 seconds
TestRunner_l2cap-tester PASS 12.35 seconds
IncrementalBuild PASS 47.78 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v4,5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests
1: T1 Title exceeds max length (83>80): "[v4,5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests"
https://github.com/bluez/bluetooth-next/pull/919
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels
2026-10-13 15:36 [PATCH v4 1/6] Bluetooth: L2CAP: Reject mode changes on connected channels Siwei Zhang
` (5 preceding siblings ...)
2026-10-13 20:18 ` [v4,1/6] Bluetooth: L2CAP: Reject mode changes on connected channels bluez.test.bot
@ 2026-10-14 17:20 ` patchwork-bot+bluetooth
6 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+bluetooth @ 2026-10-14 17:20 UTC (permalink / raw)
To: Siwei Zhang; +Cc: luiz.dentz, linux-bluetooth
Hello:
This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Tue, 13 Oct 2026 11:36:33 -0400 you wrote:
> A peer can send a configuration response with an RFC
> option for another mode to a connected channel, for
> example to switch it from Streaming to ERTM mode.
> l2cap_parse_conf_rsp() then changes chan->mode, but
> l2cap_ertm_init() is not called again, so the ERTM
> sequence lists are never allocated. The next
> out-of-sequence I-frame makes l2cap_seq_list_clear()
> write through the NULL srej_list.list.
>
> [...]
Here is the summary with links:
- [v4,1/6] Bluetooth: L2CAP: Reject mode changes on connected channels
https://git.kernel.org/bluetooth/bluetooth-next/c/0ac766c5ed8b
- [v4,2/6] Bluetooth: L2CAP: Reject signalling responses in invalid states
https://git.kernel.org/bluetooth/bluetooth-next/c/0ff5a6d955bd
- [v4,3/6] Bluetooth: L2CAP: Reject invalid TxWindow in configuration requests
https://git.kernel.org/bluetooth/bluetooth-next/c/2c5c3688eb61
- [v4,4/6] Bluetooth: L2CAP: Use default TxWindow for zero socket option
https://git.kernel.org/bluetooth/bluetooth-next/c/da927e6e6bf5
- [v4,5/6] Bluetooth: L2CAP: Only accept connection responses to outstanding requests
https://git.kernel.org/bluetooth/bluetooth-next/c/c3412d73414a
- [v4,6/6] Bluetooth: L2CAP: Remove dead configuration state code
https://git.kernel.org/bluetooth/bluetooth-next/c/734dbeb9338d
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 8+ messages in thread