Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating
[ Upstream commit 581dd2dc168fe0ed2a7a5534a724f0d3751c93ae ]
The usage of rcu_read_(un)lock while inside list_for_each_entry_rcu is
not safe since for the most part entries fetched this way shall be
treated as rcu_dereference:
Note that the value returned by rcu_dereference() is valid
only within the enclosing RCU read-side critical section [1]_.
For example, the following is **not** legal::
rcu_read_lock();
p = rcu_dereference(head.next);
rcu_read_unlock();
x = p->address; /* BUG!!! */
rcu_read_lock();
y = p->data; /* BUG!!! */
rcu_read_unlock();
Fixes: a0bfde167b
("Bluetooth: ISO: Add support for connecting multiple BISes")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
11dc486ed5
commit
0108132d7d
|
@ -6821,38 +6821,27 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
|
|||
return;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
rcu_read_lock();
|
||||
|
||||
/* Connect all BISes that are bound to the BIG */
|
||||
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
|
||||
if (bacmp(&conn->dst, BDADDR_ANY) ||
|
||||
conn->type != ISO_LINK ||
|
||||
conn->iso_qos.bcast.big != ev->handle)
|
||||
while ((conn = hci_conn_hash_lookup_big_state(hdev, ev->handle,
|
||||
BT_BOUND))) {
|
||||
if (ev->status) {
|
||||
hci_connect_cfm(conn, ev->status);
|
||||
hci_conn_del(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hci_conn_set_handle(conn,
|
||||
__le16_to_cpu(ev->bis_handle[i++])))
|
||||
continue;
|
||||
|
||||
if (!ev->status) {
|
||||
conn->state = BT_CONNECTED;
|
||||
set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
|
||||
rcu_read_unlock();
|
||||
hci_debugfs_create_conn(conn);
|
||||
hci_conn_add_sysfs(conn);
|
||||
hci_iso_setup_path(conn);
|
||||
rcu_read_lock();
|
||||
continue;
|
||||
}
|
||||
|
||||
hci_connect_cfm(conn, ev->status);
|
||||
rcu_read_unlock();
|
||||
hci_conn_del(conn);
|
||||
rcu_read_lock();
|
||||
conn->state = BT_CONNECTED;
|
||||
set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
|
||||
hci_debugfs_create_conn(conn);
|
||||
hci_conn_add_sysfs(conn);
|
||||
hci_iso_setup_path(conn);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!ev->status && !i)
|
||||
/* If no BISes have been connected for the BIG,
|
||||
* terminate. This is in case all bound connections
|
||||
|
|
Loading…
Reference in New Issue