Skip to content

Commit 7debc8a

Browse files
HaavardReifabiobaltieri
authored andcommitted
Bluetooth: Host: Add conn rsp param check
Check whether the connection response parameters both with and without ECRED are within the valid ranges from the Bluetooth Core Specification (part 3.A.4 v6.0). Changes validation checks in requests to match the same pattern. Signed-off-by: Håvard Reierstad <[email protected]>
1 parent 75dd8a3 commit 7debc8a

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

include/zephyr/bluetooth/l2cap.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,20 @@ extern "C" {
111111
*/
112112
#define BT_L2CAP_ECRED_MIN_MPS 64
113113

114+
/** @brief L2CAP maximum MTU
115+
*
116+
* The maximum MTU for an L2CAP Based Connection. This is the same with or without ECRED. This
117+
* requirement is taken from text in Core 3.A.4.22 and 3.A.4.26 v6.0.
118+
*/
119+
#define BT_L2CAP_MAX_MTU UINT16_MAX
120+
121+
/** @brief L2CAP maximum MPS
122+
*
123+
* The maximum MPS for an L2CAP Based Connection. This is the same with or without ECRED. This
124+
* requirement is taken from text in Core 3.A.4.22 and 3.A.4.26 v6.0.
125+
*/
126+
#define BT_L2CAP_MAX_MPS 65533
127+
114128
/** @brief The maximum number of channels in ECRED L2CAP signaling PDUs
115129
*
116130
* Currently, this is the maximum number of channels referred to in the

subsys/bluetooth/host/l2cap.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,11 +1475,6 @@ static void le_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
14751475

14761476
LOG_DBG("psm 0x%02x scid 0x%04x mtu %u mps %u credits %u", psm, scid, mtu, mps, credits);
14771477

1478-
if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS) {
1479-
LOG_ERR("Invalid LE-Conn Req params: mtu %u mps %u", mtu, mps);
1480-
return;
1481-
}
1482-
14831478
buf = l2cap_create_le_sig_pdu(BT_L2CAP_LE_CONN_RSP, ident,
14841479
sizeof(*rsp));
14851480
if (!buf) {
@@ -1489,6 +1484,16 @@ static void le_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
14891484
rsp = net_buf_add(buf, sizeof(*rsp));
14901485
(void)memset(rsp, 0, sizeof(*rsp));
14911486

1487+
/* Validate parameters. Requirements are from Core Spec v6.0, Vol 3.A.4.22. Valid credit
1488+
* range is from 0 to UINT16_MAX, thus no credit validation is needed.
1489+
*/
1490+
if (!IN_RANGE(mtu, L2CAP_LE_MIN_MTU, BT_L2CAP_MAX_MTU) ||
1491+
!IN_RANGE(mps, L2CAP_LE_MIN_MPS, BT_L2CAP_MAX_MPS)) {
1492+
LOG_ERR("Invalid le conn req params: mtu %u mps %u", mtu, mps);
1493+
result = BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
1494+
goto rsp;
1495+
}
1496+
14921497
/* Check if there is a server registered */
14931498
server = bt_l2cap_server_lookup_psm(psm);
14941499
if (!server) {
@@ -1574,8 +1579,12 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
15741579

15751580
LOG_DBG("psm 0x%02x mtu %u mps %u credits %u", psm, mtu, mps, credits);
15761581

1577-
if (mtu < BT_L2CAP_ECRED_MIN_MTU || mps < BT_L2CAP_ECRED_MIN_MPS) {
1578-
LOG_ERR("Invalid ecred conn req params. mtu %u mps %u", mtu, mps);
1582+
/* Validate parameters. Requirements are from Core Spec v6.0, Vol 3.A.4.25. */
1583+
if (!IN_RANGE(mtu, BT_L2CAP_ECRED_MIN_MTU, BT_L2CAP_MAX_MTU) ||
1584+
!IN_RANGE(mps, BT_L2CAP_ECRED_MIN_MPS, BT_L2CAP_MAX_MPS) ||
1585+
!IN_RANGE(credits, BT_L2CAP_ECRED_CREDITS_MIN, BT_L2CAP_ECRED_CREDITS_MAX)) {
1586+
LOG_ERR("Invalid le ecred conn req params: mtu %u mps %u credits %u", mtu, mps,
1587+
credits);
15791588
result = BT_L2CAP_LE_ERR_INVALID_PARAMS;
15801589
goto response;
15811590
}
@@ -1978,13 +1987,24 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19781987

19791988
LOG_DBG("dcid 0x%04x", dcid);
19801989

1981-
/* If a Destination CID is 0x0000, the channel was not
1990+
/* Validate parameters before assignment. Requirements are from Core Spec
1991+
* v6.0, Vol 3.A.4.26. If a Destination CID is 0x0000, the channel was not
19821992
* established.
19831993
*/
1984-
if (!dcid) {
1994+
if (dcid == 0U) {
19851995
bt_l2cap_chan_remove(conn, &chan->chan);
19861996
bt_l2cap_chan_del(&chan->chan);
19871997
continue;
1998+
} else if (!L2CAP_LE_CID_IS_DYN(dcid) ||
1999+
!IN_RANGE(mtu, BT_L2CAP_ECRED_MIN_MTU, BT_L2CAP_MAX_MTU) ||
2000+
!IN_RANGE(mps, BT_L2CAP_ECRED_MIN_MPS, BT_L2CAP_MAX_MPS) ||
2001+
!IN_RANGE(credits, BT_L2CAP_ECRED_CREDITS_MIN,
2002+
BT_L2CAP_ECRED_CREDITS_MAX)) {
2003+
LOG_WRN("Invalid ecred conn rsp params: dcid 0x%04x mtu %u mps %u "
2004+
"credits %u. Disconnecting.",
2005+
dcid, mtu, mps, credits);
2006+
bt_conn_disconnect(conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
2007+
return;
19882008
}
19892009

19902010
c = bt_l2cap_le_lookup_tx_cid(conn, dcid);
@@ -2082,6 +2102,20 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20822102

20832103
switch (result) {
20842104
case BT_L2CAP_LE_SUCCESS:
2105+
/* Validate parameters on successful connection. Requirements are from Core Spec
2106+
* v6.0, Vol 3.A.4.23. Valid credit range is from 0 to UINT16_MAX, thus no credit
2107+
* validation is needed.
2108+
*/
2109+
if ((!L2CAP_LE_CID_IS_DYN(dcid) ||
2110+
!IN_RANGE(mtu, L2CAP_LE_MIN_MTU, BT_L2CAP_MAX_MTU) ||
2111+
!IN_RANGE(mps, L2CAP_LE_MIN_MPS, BT_L2CAP_MAX_MPS))) {
2112+
LOG_WRN("Invalid conn rsp params: dcid 0x%04x mtu %u mps %u. "
2113+
"Disconnecting.",
2114+
dcid, mtu, mps);
2115+
bt_conn_disconnect(conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
2116+
return;
2117+
}
2118+
20852119
chan->tx.cid = dcid;
20862120
chan->tx.mtu = mtu;
20872121
chan->tx.mps = mps;

subsys/bluetooth/host/l2cap_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ struct bt_l2cap_le_credits {
125125
uint16_t credits;
126126
} __packed;
127127

128+
#define BT_L2CAP_ECRED_CREDITS_MIN 1
129+
#define BT_L2CAP_ECRED_CREDITS_MAX UINT16_MAX
130+
128131
#define BT_L2CAP_ECRED_CONN_REQ 0x17
129132
struct bt_l2cap_ecred_conn_req {
130133
uint16_t psm;

0 commit comments

Comments
 (0)