Skip to content

Commit a35c0b5

Browse files
pvgregkh
authored andcommitted
Bluetooth: ISO: use correct CIS order in Set CIG Parameters event
[ Upstream commit 71e9588 ] The order of CIS handle array in Set CIG Parameters response shall match the order of the CIS_ID array in the command (Core v5.3 Vol 4 Part E Sec 7.8.97). We send CIS_IDs mainly in the order of increasing CIS_ID (but with "last" CIS first if it has fixed CIG_ID). In handling of the reply, we currently assume this is also the same as the order of hci_conn in hdev->conn_hash, but that is not true. Match the correct hci_conn to the correct handle by matching them based on the CIG+CIS combination. The CIG+CIS combination shall be unique for ISO_LINK hci_conn at state >= BT_BOUND, which we maintain in hci_le_set_cig_params. Fixes: 26afbd8 ("Bluetooth: Add initial implementation of CIS connections") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Stable-dep-of: 0acd4ee ("Bluetooth: hci_event: validate LE Set CIG Parameters response") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ac1a7c3 commit a35c0b5

3 files changed

Lines changed: 32 additions & 22 deletions

File tree

include/net/bluetooth/hci_core.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,14 +1192,15 @@ static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev,
11921192
continue;
11931193

11941194
/* Match CIG ID if set */
1195-
if (cig != BT_ISO_QOS_CIG_UNSET && cig != c->iso_qos.ucast.cig)
1195+
if (cig != BT_ISO_QOS_CIG_UNSET && cig != c->iso_qos.cig)
11961196
continue;
11971197

11981198
/* Match CIS ID if set */
1199-
if (id != BT_ISO_QOS_CIS_UNSET && id != c->iso_qos.ucast.cis)
1199+
if (id != BT_ISO_QOS_CIS_UNSET && id != c->iso_qos.cis)
12001200
continue;
12011201

1202-
if (ba_type == c->dst_type && !bacmp(&c->dst, ba)) {
1202+
/* Match destination address if set */
1203+
if (!ba || (ba_type == c->dst_type && !bacmp(&c->dst, ba))) {
12031204
rcu_read_unlock();
12041205
return c;
12051206
}

net/bluetooth/hci_conn.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,8 +1862,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
18621862
{
18631863
struct hci_conn *cis;
18641864

1865-
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
1866-
qos->ucast.cis);
1865+
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->cig,
1866+
qos->cis);
18671867
if (!cis) {
18681868
cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
18691869
if (!cis)

net/bluetooth/hci_event.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3785,49 +3785,58 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
37853785
struct sk_buff *skb)
37863786
{
37873787
struct hci_rp_le_set_cig_params *rp = data;
3788+
struct hci_cp_le_set_cig_params *cp;
37883789
struct hci_conn *conn;
3789-
int i = 0;
3790+
u8 status = rp->status;
3791+
int i;
37903792

37913793
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
37923794

3795+
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_CIG_PARAMS);
3796+
if (!cp || rp->num_handles != cp->num_cis || rp->cig_id != cp->cig_id) {
3797+
bt_dev_err(hdev, "unexpected Set CIG Parameters response data");
3798+
status = HCI_ERROR_UNSPECIFIED;
3799+
}
3800+
37933801
hci_dev_lock(hdev);
37943802

3795-
if (rp->status) {
3803+
if (status) {
37963804
while ((conn = hci_conn_hash_lookup_cig(hdev, rp->cig_id))) {
37973805
conn->state = BT_CLOSED;
3798-
hci_connect_cfm(conn, rp->status);
3806+
hci_connect_cfm(conn, status);
37993807
hci_conn_del(conn);
38003808
}
38013809
goto unlock;
38023810
}
38033811

3804-
rcu_read_lock();
3812+
/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 2553
3813+
*
3814+
* If the Status return parameter is zero, then the Controller shall
3815+
* set the Connection_Handle arrayed return parameter to the connection
3816+
* handle(s) corresponding to the CIS configurations specified in
3817+
* the CIS_IDs command parameter, in the same order.
3818+
*/
3819+
for (i = 0; i < rp->num_handles; ++i) {
3820+
conn = hci_conn_hash_lookup_cis(hdev, NULL, 0, rp->cig_id,
3821+
cp->cis[i].cis_id);
3822+
if (!conn || !bacmp(&conn->dst, BDADDR_ANY))
3823+
continue;
38053824

3806-
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
3807-
if (conn->type != ISO_LINK || conn->iso_qos.cig != rp->cig_id ||
3808-
conn->state == BT_CONNECTED)
3825+
if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
38093826
continue;
38103827

38113828
if (HCI_CONN_HANDLE_UNSET(conn->handle))
38123829
ida_free(&hdev->unset_handle_ida, conn->handle);
3813-
conn->handle = __le16_to_cpu(rp->handle[i++]);
3830+
conn->handle = __le16_to_cpu(rp->handle[i]);
38143831

38153832
bt_dev_dbg(hdev, "%p handle 0x%4.4x link %p", conn,
38163833
conn->handle, conn->link);
38173834

38183835
/* Create CIS if LE is already connected */
3819-
if (conn->link && conn->link->state == BT_CONNECTED) {
3820-
rcu_read_unlock();
3836+
if (conn->link && conn->link->state == BT_CONNECTED)
38213837
hci_le_create_cis(conn->link);
3822-
rcu_read_lock();
3823-
}
3824-
3825-
if (i == rp->num_handles)
3826-
break;
38273838
}
38283839

3829-
rcu_read_unlock();
3830-
38313840
unlock:
38323841
hci_dev_unlock(hdev);
38333842

0 commit comments

Comments
 (0)