Re: [PATCH v1] Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 4, 2024 at 11:58 AM Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
>
> 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: a0bfde167b50 ("Bluetooth: ISO: Add support for connecting multiple BISes")
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
> ---
>  net/bluetooth/hci_event.c | 33 +++++++++++----------------------
>  1 file changed, 11 insertions(+), 22 deletions(-)
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index aca121408369..0d59f2cfb9a4 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -6872,38 +6872,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
> --
> 2.47.1
>


-- 
Luiz Augusto von Dentz





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux