mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-05 13:42:54 -04:00
Bluetooth: L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short
Test L2CAP/ECFC/BV-26-C expect the response to L2CAP_ECRED_CONN_REQ with
and MTU value < L2CAP_ECRED_MIN_MTU (64) to be L2CAP_CR_LE_INVALID_PARAMS
rather than L2CAP_CR_LE_UNACCEPT_PARAMS.
Also fix not including the correct number of CIDs in the response since
the spec requires all CIDs being rejected to be included in the
response.
Link: https://github.com/bluez/bluez/issues/1868
Fixes: 15f02b9105 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
@@ -284,9 +284,9 @@ struct l2cap_conn_rsp {
|
||||
#define L2CAP_CR_LE_BAD_KEY_SIZE 0x0007
|
||||
#define L2CAP_CR_LE_ENCRYPTION 0x0008
|
||||
#define L2CAP_CR_LE_INVALID_SCID 0x0009
|
||||
#define L2CAP_CR_LE_SCID_IN_USE 0X000A
|
||||
#define L2CAP_CR_LE_UNACCEPT_PARAMS 0X000B
|
||||
#define L2CAP_CR_LE_INVALID_PARAMS 0X000C
|
||||
#define L2CAP_CR_LE_SCID_IN_USE 0x000A
|
||||
#define L2CAP_CR_LE_UNACCEPT_PARAMS 0x000B
|
||||
#define L2CAP_CR_LE_INVALID_PARAMS 0x000C
|
||||
|
||||
/* connect/create channel status */
|
||||
#define L2CAP_CS_NO_INFO 0x0000
|
||||
|
||||
@@ -5051,13 +5051,15 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
struct l2cap_chan *chan, *pchan;
|
||||
u16 mtu, mps;
|
||||
__le16 psm;
|
||||
u8 result, len = 0;
|
||||
u8 result, rsp_len = 0;
|
||||
int i, num_scid;
|
||||
bool defer = false;
|
||||
|
||||
if (!enable_ecred)
|
||||
return -EINVAL;
|
||||
|
||||
memset(pdu, 0, sizeof(*pdu));
|
||||
|
||||
if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
|
||||
result = L2CAP_CR_LE_INVALID_PARAMS;
|
||||
goto response;
|
||||
@@ -5066,6 +5068,9 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
cmd_len -= sizeof(*req);
|
||||
num_scid = cmd_len / sizeof(u16);
|
||||
|
||||
/* Always respond with the same number of scids as in the request */
|
||||
rsp_len = cmd_len;
|
||||
|
||||
if (num_scid > L2CAP_ECRED_MAX_CID) {
|
||||
result = L2CAP_CR_LE_INVALID_PARAMS;
|
||||
goto response;
|
||||
@@ -5075,7 +5080,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
mps = __le16_to_cpu(req->mps);
|
||||
|
||||
if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
|
||||
result = L2CAP_CR_LE_UNACCEPT_PARAMS;
|
||||
result = L2CAP_CR_LE_INVALID_PARAMS;
|
||||
goto response;
|
||||
}
|
||||
|
||||
@@ -5095,8 +5100,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
|
||||
BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
|
||||
|
||||
memset(pdu, 0, sizeof(*pdu));
|
||||
|
||||
/* Check if we have socket listening on psm */
|
||||
pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
|
||||
&conn->hcon->dst, LE_LINK);
|
||||
@@ -5121,7 +5124,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
BT_DBG("scid[%d] 0x%4.4x", i, scid);
|
||||
|
||||
pdu->dcid[i] = 0x0000;
|
||||
len += sizeof(*pdu->dcid);
|
||||
|
||||
/* Check for valid dynamic CID range */
|
||||
if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
|
||||
@@ -5188,7 +5190,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
return 0;
|
||||
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
|
||||
sizeof(*pdu) + len, pdu);
|
||||
sizeof(*pdu) + rsp_len, pdu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user