* [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
2026-03-10 21:29 ` Lukas Johannes Möller
@ 2026-03-10 21:29 ` Lukas Johannes Möller
2026-03-10 21:39 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 5+ messages in thread
From: Lukas Johannes Möller @ 2026-03-10 21:29 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: security, Marcel Holtmann, Johan Hedberg, Willy Tarreau,
Lukas Johannes Möller, stable
l2cap_information_rsp() checks that cmd_len covers the fixed
l2cap_info_rsp header (type + result, 4 bytes) but then reads
rsp->data without verifying that the payload is present:
- L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads
4 bytes past the header (needs cmd_len >= 8).
- L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header
(needs cmd_len >= 5).
A truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an
out-of-bounds read of adjacent skb data.
Guard each data access with the required payload length check. If the
payload is too short, skip the read and let the state machine complete
with safe defaults (feat_mask and remote_fixed_chan remain zero from
kzalloc), so the info timer cleanup and l2cap_conn_start() still run
and the connection is not stalled.
Fixes: 4e8402a3f884 ("[Bluetooth] Retrieve L2CAP features mask on connection setup")
Cc: stable@vger.kernel.org
Signed-off-by: Lukas Johannes Möller <research@johannes-moeller.dev>
---
net/bluetooth/l2cap_core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f8ed03095592..93e41d9ac124 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4616,7 +4616,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
switch (type) {
case L2CAP_IT_FEAT_MASK:
- conn->feat_mask = get_unaligned_le32(rsp->data);
+ if (cmd_len >= sizeof(*rsp) + sizeof(u32))
+ conn->feat_mask = get_unaligned_le32(rsp->data);
if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
struct l2cap_info_req req;
@@ -4635,7 +4636,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
break;
case L2CAP_IT_FIXED_CHAN:
- conn->remote_fixed_chan = rsp->data[0];
+ if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0]))
+ conn->remote_fixed_chan = rsp->data[0];
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
conn->info_ident = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
2026-03-10 21:29 ` [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access Lukas Johannes Möller
@ 2026-03-10 21:39 ` Luiz Augusto von Dentz
0 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2026-03-10 21:39 UTC (permalink / raw)
To: Lukas Johannes Möller
Cc: security, Marcel Holtmann, Johan Hedberg, Willy Tarreau, stable
Hi Lukas,
On Tue, Mar 10, 2026 at 5:31 PM Lukas Johannes Möller
<research@johannes-moeller.dev> wrote:
>
> l2cap_information_rsp() checks that cmd_len covers the fixed
> l2cap_info_rsp header (type + result, 4 bytes) but then reads
> rsp->data without verifying that the payload is present:
>
> - L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads
> 4 bytes past the header (needs cmd_len >= 8).
>
> - L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header
> (needs cmd_len >= 5).
>
> A truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an
> out-of-bounds read of adjacent skb data.
>
> Guard each data access with the required payload length check. If the
> payload is too short, skip the read and let the state machine complete
> with safe defaults (feat_mask and remote_fixed_chan remain zero from
> kzalloc), so the info timer cleanup and l2cap_conn_start() still run
> and the connection is not stalled.
>
> Fixes: 4e8402a3f884 ("[Bluetooth] Retrieve L2CAP features mask on connection setup")
> Cc: stable@vger.kernel.org
> Signed-off-by: Lukas Johannes Möller <research@johannes-moeller.dev>
> ---
> net/bluetooth/l2cap_core.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index f8ed03095592..93e41d9ac124 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -4616,7 +4616,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
>
> switch (type) {
> case L2CAP_IT_FEAT_MASK:
> - conn->feat_mask = get_unaligned_le32(rsp->data);
> + if (cmd_len >= sizeof(*rsp) + sizeof(u32))
> + conn->feat_mask = get_unaligned_le32(rsp->data);
>
> if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
> struct l2cap_info_req req;
> @@ -4635,7 +4636,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
> break;
>
> case L2CAP_IT_FIXED_CHAN:
> - conn->remote_fixed_chan = rsp->data[0];
> + if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0]))
> + conn->remote_fixed_chan = rsp->data[0];
> conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
> conn->info_ident = 0;
>
> --
> 2.43.0
Ditto, send to linux-bluetooth so it can trigger test automation.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
@ 2026-03-10 21:59 Lukas Johannes Möller
2026-03-10 21:59 ` [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access Lukas Johannes Möller
2026-03-11 20:40 ` [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() patchwork-bot+bluetooth
0 siblings, 2 replies; 5+ messages in thread
From: Lukas Johannes Möller @ 2026-03-10 21:59 UTC (permalink / raw)
To: linux-bluetooth
Cc: Luiz Augusto von Dentz, Lukas Johannes Möller, stable
l2cap_ecred_reconf_rsp() casts the incoming data to struct
l2cap_ecred_conn_rsp (the ECRED *connection* response, 8 bytes with
result at offset 6) instead of struct l2cap_ecred_reconf_rsp (2 bytes
with result at offset 0).
This causes two problems:
- The sizeof(*rsp) length check requires 8 bytes instead of the
correct 2, so valid L2CAP_ECRED_RECONF_RSP packets are rejected
with -EPROTO.
- rsp->result reads from offset 6 instead of offset 0, returning
wrong data when the packet is large enough to pass the check.
Fix by using the correct type. Also pass the already byte-swapped
result variable to BT_DBG instead of the raw __le16 field.
Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Cc: stable@vger.kernel.org
Signed-off-by: Lukas Johannes Möller <research@johannes-moeller.dev>
---
net/bluetooth/l2cap_core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ad98db9632fd..f8ed03095592 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5424,7 +5424,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
u8 *data)
{
struct l2cap_chan *chan, *tmp;
- struct l2cap_ecred_conn_rsp *rsp = (void *) data;
+ struct l2cap_ecred_reconf_rsp *rsp = (void *) data;
u16 result;
if (cmd_len < sizeof(*rsp))
@@ -5432,7 +5432,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
result = __le16_to_cpu(rsp->result);
- BT_DBG("result 0x%4.4x", rsp->result);
+ BT_DBG("result 0x%4.4x", result);
if (!result)
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
2026-03-10 21:59 [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() Lukas Johannes Möller
@ 2026-03-10 21:59 ` Lukas Johannes Möller
2026-03-11 20:40 ` [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() patchwork-bot+bluetooth
1 sibling, 0 replies; 5+ messages in thread
From: Lukas Johannes Möller @ 2026-03-10 21:59 UTC (permalink / raw)
To: linux-bluetooth
Cc: Luiz Augusto von Dentz, Lukas Johannes Möller, stable
l2cap_information_rsp() checks that cmd_len covers the fixed
l2cap_info_rsp header (type + result, 4 bytes) but then reads
rsp->data without verifying that the payload is present:
- L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads
4 bytes past the header (needs cmd_len >= 8).
- L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header
(needs cmd_len >= 5).
A truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an
out-of-bounds read of adjacent skb data.
Guard each data access with the required payload length check. If the
payload is too short, skip the read and let the state machine complete
with safe defaults (feat_mask and remote_fixed_chan remain zero from
kzalloc), so the info timer cleanup and l2cap_conn_start() still run
and the connection is not stalled.
Fixes: 4e8402a3f884 ("[Bluetooth] Retrieve L2CAP features mask on connection setup")
Cc: stable@vger.kernel.org
Signed-off-by: Lukas Johannes Möller <research@johannes-moeller.dev>
---
net/bluetooth/l2cap_core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f8ed03095592..93e41d9ac124 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4616,7 +4616,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
switch (type) {
case L2CAP_IT_FEAT_MASK:
- conn->feat_mask = get_unaligned_le32(rsp->data);
+ if (cmd_len >= sizeof(*rsp) + sizeof(u32))
+ conn->feat_mask = get_unaligned_le32(rsp->data);
if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
struct l2cap_info_req req;
@@ -4635,7 +4636,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
break;
case L2CAP_IT_FIXED_CHAN:
- conn->remote_fixed_chan = rsp->data[0];
+ if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0]))
+ conn->remote_fixed_chan = rsp->data[0];
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
conn->info_ident = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
2026-03-10 21:59 [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() Lukas Johannes Möller
2026-03-10 21:59 ` [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access Lukas Johannes Möller
@ 2026-03-11 20:40 ` patchwork-bot+bluetooth
1 sibling, 0 replies; 5+ messages in thread
From: patchwork-bot+bluetooth @ 2026-03-11 20:40 UTC (permalink / raw)
To: =?utf-8?q?Lukas_Johannes_M=C3=B6ller_=3Cresearch=40johannes-moeller=2Edev=3E?=
Cc: linux-bluetooth, luiz.dentz, stable
Hello:
This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Tue, 10 Mar 2026 21:59:46 +0000 you wrote:
> l2cap_ecred_reconf_rsp() casts the incoming data to struct
> l2cap_ecred_conn_rsp (the ECRED *connection* response, 8 bytes with
> result at offset 6) instead of struct l2cap_ecred_reconf_rsp (2 bytes
> with result at offset 0).
>
> This causes two problems:
>
> [...]
Here is the summary with links:
- [1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
(no matching commit)
- [2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
https://git.kernel.org/bluetooth/bluetooth-next/c/4b0c8bb9885a
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] 5+ messages in thread
end of thread, other threads:[~2026-03-11 20:40 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 21:59 [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() Lukas Johannes Möller
2026-03-10 21:59 ` [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access Lukas Johannes Möller
2026-03-11 20:40 ` [PATCH 1/2] Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp() patchwork-bot+bluetooth
[not found] <abBJh7sJ11RKVGhd@1wt.eu>
2026-03-10 21:29 ` Lukas Johannes Möller
2026-03-10 21:29 ` [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access Lukas Johannes Möller
2026-03-10 21:39 ` Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox