Skip to content

Commit ab39b11

Browse files
committed
Merge tag 'for-net-2023-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - Fixes to debugfs registration - Fix use-after-free in hci_remove_ltk/hci_remove_irk - Fixes to ISO channel support - Fix missing checks for invalid L2CAP DCID - Fix l2cap_disconnect_req deadlock - Add lock to protect HCI_UNREGISTER * tag 'for-net-2023-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: L2CAP: Add missing checks for invalid DCID Bluetooth: ISO: use correct CIS order in Set CIG Parameters event Bluetooth: ISO: don't try to remove CIG if there are bound CIS left Bluetooth: Fix l2cap_disconnect_req deadlock Bluetooth: hci_qca: fix debugfs registration Bluetooth: fix debugfs registration Bluetooth: hci_sync: add lock to protect HCI_UNREGISTER Bluetooth: Fix use-after-free in hci_remove_ltk/hci_remove_irk Bluetooth: ISO: Fix CIG auto-allocation to select configurable CIG Bluetooth: ISO: consider right CIS when removing CIG at cleanup ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 20c4764 + 7576721 commit ab39b11

File tree

8 files changed

+84
-39
lines changed

8 files changed

+84
-39
lines changed

drivers/bluetooth/hci_qca.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ enum qca_flags {
7878
QCA_HW_ERROR_EVENT,
7979
QCA_SSR_TRIGGERED,
8080
QCA_BT_OFF,
81-
QCA_ROM_FW
81+
QCA_ROM_FW,
82+
QCA_DEBUGFS_CREATED,
8283
};
8384

8485
enum qca_capabilities {
@@ -635,6 +636,9 @@ static void qca_debugfs_init(struct hci_dev *hdev)
635636
if (!hdev->debugfs)
636637
return;
637638

639+
if (test_and_set_bit(QCA_DEBUGFS_CREATED, &qca->flags))
640+
return;
641+
638642
ibs_dir = debugfs_create_dir("ibs", hdev->debugfs);
639643

640644
/* read only */

include/net/bluetooth/hci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ enum {
350350
enum {
351351
HCI_SETUP,
352352
HCI_CONFIG,
353+
HCI_DEBUGFS_CREATED,
353354
HCI_AUTO_OFF,
354355
HCI_RFKILLED,
355356
HCI_MGMT,

include/net/bluetooth/hci_core.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ struct hci_dev {
515515
struct work_struct cmd_sync_work;
516516
struct list_head cmd_sync_work_list;
517517
struct mutex cmd_sync_work_lock;
518+
struct mutex unregister_lock;
518519
struct work_struct cmd_sync_cancel_work;
519520
struct work_struct reenable_adv_work;
520521

@@ -1201,7 +1202,8 @@ static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev,
12011202
if (id != BT_ISO_QOS_CIS_UNSET && id != c->iso_qos.ucast.cis)
12021203
continue;
12031204

1204-
if (ba_type == c->dst_type && !bacmp(&c->dst, ba)) {
1205+
/* Match destination address if set */
1206+
if (!ba || (ba_type == c->dst_type && !bacmp(&c->dst, ba))) {
12051207
rcu_read_unlock();
12061208
return c;
12071209
}

net/bluetooth/hci_conn.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -947,8 +947,8 @@ static void find_cis(struct hci_conn *conn, void *data)
947947
{
948948
struct iso_list_data *d = data;
949949

950-
/* Ignore broadcast */
951-
if (!bacmp(&conn->dst, BDADDR_ANY))
950+
/* Ignore broadcast or if CIG don't match */
951+
if (!bacmp(&conn->dst, BDADDR_ANY) || d->cig != conn->iso_qos.ucast.cig)
952952
return;
953953

954954
d->count++;
@@ -963,12 +963,17 @@ static void cis_cleanup(struct hci_conn *conn)
963963
struct hci_dev *hdev = conn->hdev;
964964
struct iso_list_data d;
965965

966+
if (conn->iso_qos.ucast.cig == BT_ISO_QOS_CIG_UNSET)
967+
return;
968+
966969
memset(&d, 0, sizeof(d));
967970
d.cig = conn->iso_qos.ucast.cig;
968971

969972
/* Check if ISO connection is a CIS and remove CIG if there are
970973
* no other connections using it.
971974
*/
975+
hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_BOUND, &d);
976+
hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_CONNECT, &d);
972977
hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_CONNECTED, &d);
973978
if (d.count)
974979
return;
@@ -1766,24 +1771,23 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos)
17661771

17671772
memset(&data, 0, sizeof(data));
17681773

1769-
/* Allocate a CIG if not set */
1774+
/* Allocate first still reconfigurable CIG if not set */
17701775
if (qos->ucast.cig == BT_ISO_QOS_CIG_UNSET) {
1771-
for (data.cig = 0x00; data.cig < 0xff; data.cig++) {
1776+
for (data.cig = 0x00; data.cig < 0xf0; data.cig++) {
17721777
data.count = 0;
1773-
data.cis = 0xff;
17741778

1775-
hci_conn_hash_list_state(hdev, cis_list, ISO_LINK,
1776-
BT_BOUND, &data);
1779+
hci_conn_hash_list_state(hdev, find_cis, ISO_LINK,
1780+
BT_CONNECT, &data);
17771781
if (data.count)
17781782
continue;
17791783

1780-
hci_conn_hash_list_state(hdev, cis_list, ISO_LINK,
1784+
hci_conn_hash_list_state(hdev, find_cis, ISO_LINK,
17811785
BT_CONNECTED, &data);
17821786
if (!data.count)
17831787
break;
17841788
}
17851789

1786-
if (data.cig == 0xff)
1790+
if (data.cig == 0xf0)
17871791
return false;
17881792

17891793
/* Update CIG */

net/bluetooth/hci_core.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,10 +1416,10 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
14161416

14171417
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
14181418
{
1419-
struct smp_ltk *k;
1419+
struct smp_ltk *k, *tmp;
14201420
int removed = 0;
14211421

1422-
list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
1422+
list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
14231423
if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
14241424
continue;
14251425

@@ -1435,9 +1435,9 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
14351435

14361436
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
14371437
{
1438-
struct smp_irk *k;
1438+
struct smp_irk *k, *tmp;
14391439

1440-
list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
1440+
list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
14411441
if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type)
14421442
continue;
14431443

@@ -2686,7 +2686,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
26862686
{
26872687
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
26882688

2689+
mutex_lock(&hdev->unregister_lock);
26892690
hci_dev_set_flag(hdev, HCI_UNREGISTER);
2691+
mutex_unlock(&hdev->unregister_lock);
26902692

26912693
write_lock(&hci_dev_list_lock);
26922694
list_del(&hdev->list);

net/bluetooth/hci_event.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3804,48 +3804,56 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38043804
struct sk_buff *skb)
38053805
{
38063806
struct hci_rp_le_set_cig_params *rp = data;
3807+
struct hci_cp_le_set_cig_params *cp;
38073808
struct hci_conn *conn;
3808-
int i = 0;
3809+
u8 status = rp->status;
3810+
int i;
38093811

38103812
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
38113813

3814+
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_CIG_PARAMS);
3815+
if (!cp || rp->num_handles != cp->num_cis || rp->cig_id != cp->cig_id) {
3816+
bt_dev_err(hdev, "unexpected Set CIG Parameters response data");
3817+
status = HCI_ERROR_UNSPECIFIED;
3818+
}
3819+
38123820
hci_dev_lock(hdev);
38133821

3814-
if (rp->status) {
3822+
if (status) {
38153823
while ((conn = hci_conn_hash_lookup_cig(hdev, rp->cig_id))) {
38163824
conn->state = BT_CLOSED;
3817-
hci_connect_cfm(conn, rp->status);
3825+
hci_connect_cfm(conn, status);
38183826
hci_conn_del(conn);
38193827
}
38203828
goto unlock;
38213829
}
38223830

3823-
rcu_read_lock();
3831+
/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 2553
3832+
*
3833+
* If the Status return parameter is zero, then the Controller shall
3834+
* set the Connection_Handle arrayed return parameter to the connection
3835+
* handle(s) corresponding to the CIS configurations specified in
3836+
* the CIS_IDs command parameter, in the same order.
3837+
*/
3838+
for (i = 0; i < rp->num_handles; ++i) {
3839+
conn = hci_conn_hash_lookup_cis(hdev, NULL, 0, rp->cig_id,
3840+
cp->cis[i].cis_id);
3841+
if (!conn || !bacmp(&conn->dst, BDADDR_ANY))
3842+
continue;
38243843

3825-
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
3826-
if (conn->type != ISO_LINK ||
3827-
conn->iso_qos.ucast.cig != rp->cig_id ||
3828-
conn->state == BT_CONNECTED)
3844+
if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
38293845
continue;
38303846

3831-
conn->handle = __le16_to_cpu(rp->handle[i++]);
3847+
conn->handle = __le16_to_cpu(rp->handle[i]);
38323848

38333849
bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
38343850
conn->handle, conn->parent);
38353851

38363852
/* Create CIS if LE is already connected */
3837-
if (conn->parent && conn->parent->state == BT_CONNECTED) {
3838-
rcu_read_unlock();
3853+
if (conn->parent && conn->parent->state == BT_CONNECTED)
38393854
hci_le_create_cis(conn);
3840-
rcu_read_lock();
3841-
}
3842-
3843-
if (i == rp->num_handles)
3844-
break;
38453855
}
38463856

3847-
rcu_read_unlock();
3848-
38493857
unlock:
38503858
hci_dev_unlock(hdev);
38513859

net/bluetooth/hci_sync.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
629629
INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
630630
INIT_LIST_HEAD(&hdev->cmd_sync_work_list);
631631
mutex_init(&hdev->cmd_sync_work_lock);
632+
mutex_init(&hdev->unregister_lock);
632633

633634
INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
634635
INIT_WORK(&hdev->reenable_adv_work, reenable_adv);
@@ -692,14 +693,19 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
692693
void *data, hci_cmd_sync_work_destroy_t destroy)
693694
{
694695
struct hci_cmd_sync_work_entry *entry;
696+
int err = 0;
695697

696-
if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
697-
return -ENODEV;
698+
mutex_lock(&hdev->unregister_lock);
699+
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
700+
err = -ENODEV;
701+
goto unlock;
702+
}
698703

699704
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
700-
if (!entry)
701-
return -ENOMEM;
702-
705+
if (!entry) {
706+
err = -ENOMEM;
707+
goto unlock;
708+
}
703709
entry->func = func;
704710
entry->data = data;
705711
entry->destroy = destroy;
@@ -710,7 +716,9 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
710716

711717
queue_work(hdev->req_workqueue, &hdev->cmd_sync_work);
712718

713-
return 0;
719+
unlock:
720+
mutex_unlock(&hdev->unregister_lock);
721+
return err;
714722
}
715723
EXPORT_SYMBOL(hci_cmd_sync_submit);
716724

@@ -4543,6 +4551,9 @@ static int hci_init_sync(struct hci_dev *hdev)
45434551
!hci_dev_test_flag(hdev, HCI_CONFIG))
45444552
return 0;
45454553

4554+
if (hci_dev_test_and_set_flag(hdev, HCI_DEBUGFS_CREATED))
4555+
return 0;
4556+
45464557
hci_debugfs_create_common(hdev);
45474558

45484559
if (lmp_bredr_capable(hdev))

net/bluetooth/l2cap_core.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4306,6 +4306,10 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
43064306
result = __le16_to_cpu(rsp->result);
43074307
status = __le16_to_cpu(rsp->status);
43084308

4309+
if (result == L2CAP_CR_SUCCESS && (dcid < L2CAP_CID_DYN_START ||
4310+
dcid > L2CAP_CID_DYN_END))
4311+
return -EPROTO;
4312+
43094313
BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
43104314
dcid, scid, result, status);
43114315

@@ -4337,6 +4341,11 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
43374341

43384342
switch (result) {
43394343
case L2CAP_CR_SUCCESS:
4344+
if (__l2cap_get_chan_by_dcid(conn, dcid)) {
4345+
err = -EBADSLT;
4346+
break;
4347+
}
4348+
43404349
l2cap_state_change(chan, BT_CONFIG);
43414350
chan->ident = 0;
43424351
chan->dcid = dcid;
@@ -4663,7 +4672,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
46634672

46644673
chan->ops->set_shutdown(chan);
46654674

4675+
l2cap_chan_unlock(chan);
46664676
mutex_lock(&conn->chan_lock);
4677+
l2cap_chan_lock(chan);
46674678
l2cap_chan_del(chan, ECONNRESET);
46684679
mutex_unlock(&conn->chan_lock);
46694680

@@ -4702,7 +4713,9 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
47024713
return 0;
47034714
}
47044715

4716+
l2cap_chan_unlock(chan);
47054717
mutex_lock(&conn->chan_lock);
4718+
l2cap_chan_lock(chan);
47064719
l2cap_chan_del(chan, 0);
47074720
mutex_unlock(&conn->chan_lock);
47084721

0 commit comments

Comments
 (0)