Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/2 Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
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.
--- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +2 -2
@@ -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 ;
Signature · 1 line
2.43.0
Luiz Augusto von Dentz
maintainerHi Lukas,
Quoted 48 lines · Lukas Johannes Möller
l2cap_ecred_reconf_rsp()casts the incoming data to structl2cap_ecred_conn_rsp(the ECRED *connection* response, 8 bytes with result at offset 6) instead of structl2cap_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 validL2CAP_ECRED_RECONF_RSPpackets are rejected with-EPROTO.-
rsp->resultreads 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_DBGinstead of the raw__le16field.Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")Signed-off-by Lukas Johannes Möller <[email protected]>--- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)net/bluetooth/l2cap_core.c +2
-3@@ -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 ; --
Quoted 1 line
2.43.0
Looks good, but need to include linux-bluetooth so CI can pickup and check if there are any regressions caused by this change.
Signature · 1 line
Luiz Augusto von Dentz
PATCH 2/2 Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
In reply to Lukas Johannes Möllerl2cap_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.
--- net/bluetooth/l2cap_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +4 -2
@@ -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 ;
Signature · 1 line
2.43.0
Luiz Augusto von Dentz
maintainerRe: [PATCH 2/2] Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
Hi Lukas,
Quoted 52 lines · Lukas Johannes Möller
l2cap_information_rsp()checks thatcmd_lencovers the fixedl2cap_info_rspheader (type + result, 4 bytes) but then readsrsp->datawithout verifying that the payload is present:-
L2CAP_IT_FEAT_MASKcallsget_unaligned_le32(rsp->data), which reads 4 bytes past the header (needscmd_len>= 8).-
L2CAP_IT_FIXED_CHANreads rsp->data[0], 1 byte past the header (needscmd_len>= 5).A truncated
L2CAP_INFO_RSPwith result ==L2CAP_IR_SUCCESStriggers 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_maskandremote_fixed_chanremain zero from kzalloc), so the info timer cleanup andl2cap_conn_start()still run and the connection is not stalled.Fixes 4e8402a3f884 ("[Bluetooth] Retrieve L2CAP features mask on connection setup")Signed-off-by Lukas Johannes Möller <[email protected]>--- net/bluetooth/l2cap_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)net/bluetooth/l2cap_core.c +4
-3@@ -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 ; --
Quoted 1 line
2.43.0
Ditto, send to linux-bluetooth so it can trigger test automation.
Signature · 1 line
Luiz Augusto von Dentz