@@ -1915,6 +1915,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1915
1915
uint16_t dcid , mtu , mps , credits , result , psm ;
1916
1916
uint8_t attempted = 0 ;
1917
1917
uint8_t succeeded = 0 ;
1918
+ bool valid_params = true;
1918
1919
1919
1920
if (buf -> len < sizeof (* rsp )) {
1920
1921
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,
1929
1930
1930
1931
LOG_DBG ("mtu 0x%04x mps 0x%04x credits 0x%04x result %u" , mtu , mps , credits , result );
1931
1932
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
+
1932
1953
chan = l2cap_lookup_ident (conn , ident );
1933
1954
if (chan ) {
1934
1955
psm = chan -> psm ;
@@ -1978,9 +1999,9 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1978
1999
LOG_DBG ("dcid 0x%04x" , dcid );
1979
2000
1980
2001
/* If a Destination CID is 0x0000, the channel was not
1981
- * established.
2002
+ * established. The DCID shall also be from the dynamic range.
1982
2003
*/
1983
- if (!dcid ) {
2004
+ if (!dcid || ! L2CAP_LE_CID_IS_DYN ( dcid ) ) {
1984
2005
bt_l2cap_chan_remove (conn , & chan -> chan );
1985
2006
bt_l2cap_chan_del (& chan -> chan );
1986
2007
continue ;
@@ -2043,6 +2064,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2043
2064
struct bt_l2cap_le_chan * chan ;
2044
2065
struct bt_l2cap_le_conn_rsp * rsp = (void * )buf -> data ;
2045
2066
uint16_t dcid , mtu , mps , credits , result ;
2067
+ bool valid_params = true;
2046
2068
2047
2069
if (buf -> len != sizeof (* rsp )) {
2048
2070
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,
2059
2081
LOG_DBG ("dcid 0x%04x mtu %u mps %u credits %u result 0x%04x" , dcid , mtu , mps , credits ,
2060
2082
result );
2061
2083
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
+
2062
2110
/* Keep the channel in case of security errors */
2063
2111
if (result == BT_L2CAP_LE_SUCCESS ||
2064
2112
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
0 commit comments