Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: L2CAP: Fix not checking for maximum number of DCID

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>

authored by

Luiz Augusto von Dentz and committed by
Marcel Holtmann
7cf3b1dd c06632a4

+10 -3
+1
include/net/bluetooth/l2cap.h
··· 494 494 495 495 #define L2CAP_ECRED_MIN_MTU 64 496 496 #define L2CAP_ECRED_MIN_MPS 64 497 + #define L2CAP_ECRED_MAX_CID 5 497 498 498 499 struct l2cap_ecred_conn_req { 499 500 __le16 psm;
+9 -3
net/bluetooth/l2cap_core.c
··· 5921 5921 struct l2cap_ecred_conn_req *req = (void *) data; 5922 5922 struct { 5923 5923 struct l2cap_ecred_conn_rsp rsp; 5924 - __le16 dcid[5]; 5924 + __le16 dcid[L2CAP_ECRED_MAX_CID]; 5925 5925 } __packed pdu; 5926 5926 struct l2cap_chan *chan, *pchan; 5927 5927 u16 mtu, mps; ··· 5934 5934 return -EINVAL; 5935 5935 5936 5936 if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 5937 + result = L2CAP_CR_LE_INVALID_PARAMS; 5938 + goto response; 5939 + } 5940 + 5941 + cmd_len -= sizeof(*req); 5942 + num_scid = cmd_len / sizeof(u16); 5943 + 5944 + if (num_scid > ARRAY_SIZE(pdu.dcid)) { 5937 5945 result = L2CAP_CR_LE_INVALID_PARAMS; 5938 5946 goto response; 5939 5947 } ··· 5978 5970 } 5979 5971 5980 5972 result = L2CAP_CR_LE_SUCCESS; 5981 - cmd_len -= sizeof(*req); 5982 - num_scid = cmd_len / sizeof(u16); 5983 5973 5984 5974 for (i = 0; i < num_scid; i++) { 5985 5975 u16 scid = __le16_to_cpu(req->scid[i]);