Bluetooth: L2CAP: Fix not checking for maximum number of DCID
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 15 Mar 2021 20:04:37 +0000 (13:04 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 15 Mar 2021 20:08:33 +0000 (21:08 +0100)
When receiving L2CAP_CREDIT_BASED_CONNECTION_REQ the remote may request
more channels than allowed by the spec (10 octecs = 5 CIDs) so this
checks if the number of channels is bigger than the maximum allowed and
respond with an error.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/l2cap.h
net/bluetooth/l2cap_core.c

index 61800a7..3c4f550 100644 (file)
@@ -494,6 +494,7 @@ struct l2cap_le_credits {
 
 #define L2CAP_ECRED_MIN_MTU            64
 #define L2CAP_ECRED_MIN_MPS            64
+#define L2CAP_ECRED_MAX_CID            5
 
 struct l2cap_ecred_conn_req {
        __le16 psm;
index 72c2f52..374cc32 100644 (file)
@@ -5921,7 +5921,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
        struct l2cap_ecred_conn_req *req = (void *) data;
        struct {
                struct l2cap_ecred_conn_rsp rsp;
-               __le16 dcid[5];
+               __le16 dcid[L2CAP_ECRED_MAX_CID];
        } __packed pdu;
        struct l2cap_chan *chan, *pchan;
        u16 mtu, mps;
@@ -5938,6 +5938,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
                goto response;
        }
 
+       cmd_len -= sizeof(*req);
+       num_scid = cmd_len / sizeof(u16);
+
+       if (num_scid > ARRAY_SIZE(pdu.dcid)) {
+               result = L2CAP_CR_LE_INVALID_PARAMS;
+               goto response;
+       }
+
        mtu  = __le16_to_cpu(req->mtu);
        mps  = __le16_to_cpu(req->mps);
 
@@ -5970,8 +5978,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
        }
 
        result = L2CAP_CR_LE_SUCCESS;
-       cmd_len -= sizeof(*req);
-       num_scid = cmd_len / sizeof(u16);
 
        for (i = 0; i < num_scid; i++) {
                u16 scid = __le16_to_cpu(req->scid[i]);