Skip to content

Commit 86ec0c2

Browse files
committed
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). Signed-off-by: Håvard Reierstad <[email protected]>
1 parent 322da1d commit 86ec0c2

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

include/zephyr/bluetooth/l2cap.h

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

114+
/** @brief L2CAP maximum MPS
115+
*
116+
* The maximum MPS 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_MPS 65533
120+
114121
/** @brief The maximum number of channels in ECRED L2CAP signaling PDUs
115122
*
116123
* Currently, this is the maximum number of channels referred to in the

subsys/bluetooth/host/l2cap.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19151915
uint16_t dcid, mtu, mps, credits, result, psm;
19161916
uint8_t attempted = 0;
19171917
uint8_t succeeded = 0;
1918+
bool valid_params = true;
19181919

19191920
if (buf->len < sizeof(*rsp)) {
19201921
LOG_ERR("Too small ecred conn rsp packet size");
@@ -1929,6 +1930,26 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19291930

19301931
LOG_DBG("mtu 0x%04x mps 0x%04x credits 0x%04x result %u", mtu, mps, credits, result);
19311932

1933+
/* Validate parameters. There are no limits for
1934+
* credits as values from 0 to UINT16_MAX are valid.
1935+
*/
1936+
if (!IN_RANGE(mtu, BT_L2CAP_ECRED_MIN_MTU, UINT16_MAX)) {
1937+
LOG_WRN("Invalid mtu %u", mtu);
1938+
valid_params = false;
1939+
} else if (!IN_RANGE(mps, BT_L2CAP_ECRED_MIN_MPS, BT_L2CAP_MAX_MPS)) {
1940+
LOG_WRN("Invalid mps %u", mps);
1941+
valid_params = false;
1942+
}
1943+
1944+
if (!valid_params) {
1945+
LOG_WRN("Invalid ecred conn rsp parameters, terminating connection");
1946+
while ((chan = l2cap_remove_ident(conn, ident))) {
1947+
bt_l2cap_chan_remove(conn, &chan->chan);
1948+
bt_l2cap_chan_del(&chan->chan);
1949+
}
1950+
return;
1951+
}
1952+
19321953
chan = l2cap_lookup_ident(conn, ident);
19331954
if (chan) {
19341955
psm = chan->psm;
@@ -1978,9 +1999,9 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19781999
LOG_DBG("dcid 0x%04x", dcid);
19792000

19802001
/* If a Destination CID is 0x0000, the channel was not
1981-
* established.
2002+
* established. The DCID shall also be from the dynamic range.
19822003
*/
1983-
if (!dcid) {
2004+
if (!dcid || !L2CAP_LE_CID_IS_DYN(dcid)) {
19842005
bt_l2cap_chan_remove(conn, &chan->chan);
19852006
bt_l2cap_chan_del(&chan->chan);
19862007
continue;
@@ -2043,6 +2064,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20432064
struct bt_l2cap_le_chan *chan;
20442065
struct bt_l2cap_le_conn_rsp *rsp = (void *)buf->data;
20452066
uint16_t dcid, mtu, mps, credits, result;
2067+
bool valid_params = true;
20462068

20472069
if (buf->len != sizeof(*rsp)) {
20482070
LOG_ERR("Invalid LE conn rsp packet size (%u != %zu)",
@@ -2059,6 +2081,32 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20592081
LOG_DBG("dcid 0x%04x mtu %u mps %u credits %u result 0x%04x", dcid, mtu, mps, credits,
20602082
result);
20612083

2084+
/* Validate parameters. There are no limits for
2085+
* credits as values from 0 to UINT16_MAX are valid.
2086+
*/
2087+
if (!L2CAP_LE_CID_IS_DYN(dcid)) {
2088+
LOG_WRN("dcid 0x%04x is not dynamic", dcid);
2089+
valid_params = false;
2090+
} else if (!IN_RANGE(mtu, L2CAP_LE_MIN_MTU, UINT16_MAX)) {
2091+
LOG_WRN("Invalid mtu: %u", mtu);
2092+
valid_params = false;
2093+
} else if (!IN_RANGE(mps, L2CAP_LE_MIN_MPS, BT_L2CAP_MAX_MPS)) {
2094+
LOG_WRN("Invalid mps: %u", mps);
2095+
valid_params = false;
2096+
}
2097+
2098+
if (!valid_params) {
2099+
LOG_WRN("Invalid conn rsp parameters, terminating connection");
2100+
chan = l2cap_remove_ident(conn, ident);
2101+
if (chan) {
2102+
bt_l2cap_chan_remove(conn, &chan->chan);
2103+
bt_l2cap_chan_del(&chan->chan);
2104+
} else {
2105+
LOG_WRN("Cannot find channel for ident %u", ident);
2106+
}
2107+
return;
2108+
}
2109+
20622110
/* Keep the channel in case of security errors */
20632111
if (result == BT_L2CAP_LE_SUCCESS ||
20642112
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||

0 commit comments

Comments
 (0)