Re: [PATCH 3/3] Bluetooth: Add missing hci_dev locking when calling mgmt functions

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

 



Hi Johan,

On Tue, Nov 8, 2011 at 8:40 PM,  <johan.hedberg@xxxxxxxxx> wrote:
> From: Johan Hedberg <johan.hedberg@xxxxxxxxx>
>
> Now that the pending commands are within struct hci_dev we can properly
> control access to them throught the hci_dev locking mechanism.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@xxxxxxxxx>
> ---
>  net/bluetooth/hci_core.c  |   12 ++++++++++--
>  net/bluetooth/hci_event.c |   45 ++++++++++++++++++++++++++++++++++++++++-----
>  net/bluetooth/mgmt.c      |   13 +++++++------
>  3 files changed, 57 insertions(+), 13 deletions(-)
>
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index e5cf013..f87bf24 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -549,8 +549,11 @@ int hci_dev_open(__u16 dev)
>                hci_dev_hold(hdev);
>                set_bit(HCI_UP, &hdev->flags);
>                hci_notify(hdev, HCI_DEV_UP);
> -               if (!test_bit(HCI_SETUP, &hdev->flags))
> +               if (!test_bit(HCI_SETUP, &hdev->flags)) {
> +                       hci_dev_lock_bh(hdev);
>                        mgmt_powered(hdev, 1);
> +                       hci_dev_unlock_bh(hdev);

Shall we acquire lock before test_bit here and below?

Regards,
Andrei

> +               }
>        } else {
>                /* Init failed, cleanup */
>                tasklet_kill(&hdev->rx_task);
> @@ -642,7 +645,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
>         * and no tasks are scheduled. */
>        hdev->close(hdev);
>
> +       hci_dev_lock_bh(hdev);
>        mgmt_powered(hdev, 0);
> +       hci_dev_unlock_bh(hdev);
>
>        /* Clear flags */
>        hdev->flags = 0;
> @@ -1561,8 +1566,11 @@ void hci_unregister_dev(struct hci_dev *hdev)
>                kfree_skb(hdev->reassembly[i]);
>
>        if (!test_bit(HCI_INIT, &hdev->flags) &&
> -                                       !test_bit(HCI_SETUP, &hdev->flags))
> +                                       !test_bit(HCI_SETUP, &hdev->flags)) {
> +               hci_dev_lock_bh(hdev);
>                mgmt_index_removed(hdev);
> +               hci_dev_unlock_bh(hdev);
> +       }
>
>        /* mgmt_index_removed should take care of emptying the
>         * pending list */
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 8303f8f..a89cf1f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -60,7 +60,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
>
>        clear_bit(HCI_INQUIRY, &hdev->flags);
>
> +       hci_dev_lock(hdev);
>        mgmt_discovering(hdev, 0);
> +       hci_dev_unlock(hdev);
>
>        hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
>
> @@ -201,13 +203,15 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
>        if (!sent)
>                return;
>
> +       hci_dev_lock(hdev);
> +
>        if (test_bit(HCI_MGMT, &hdev->flags))
>                mgmt_set_local_name_complete(hdev, sent, status);
>
> -       if (status)
> -               return;
> +       if (status == 0)
> +               memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
>
> -       memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
> +       hci_dev_unlock(hdev);
>  }
>
>  static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
> @@ -282,6 +286,8 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
>
>        param = *((__u8 *) sent);
>
> +       hci_dev_lock(hdev);
> +
>        if (status != 0) {
>                mgmt_write_scan_failed(hdev, param, status);
>                hdev->discov_timeout = 0;
> @@ -311,6 +317,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
>                mgmt_connectable(hdev, 0);
>
>  done:
> +       hci_dev_unlock(hdev);
>        hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
>  }
>
> @@ -834,19 +841,24 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
>
>        BT_DBG("%s status 0x%x", hdev->name, rp->status);
>
> +       hci_dev_lock(hdev);
> +
>        if (test_bit(HCI_MGMT, &hdev->flags))
>                mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
>
>        if (rp->status != 0)
> -               return;
> +               goto unlock;
>
>        cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
>        if (!cp)
> -               return;
> +               goto unlock;
>
>        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
>        if (conn)
>                conn->pin_length = cp->pin_len;
> +
> +unlock:
> +       hci_dev_unlock(hdev);
>  }
>
>  static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
> @@ -855,10 +867,15 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
>
>        BT_DBG("%s status 0x%x", hdev->name, rp->status);
>
> +       hci_dev_lock(hdev);
> +
>        if (test_bit(HCI_MGMT, &hdev->flags))
>                mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
>                                                                rp->status);
> +
> +       hci_dev_unlock(hdev);
>  }
> +
>  static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
>                                       struct sk_buff *skb)
>  {
> @@ -885,9 +902,13 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
>
>        BT_DBG("%s status 0x%x", hdev->name, rp->status);
>
> +       hci_dev_lock(hdev);
> +
>        if (test_bit(HCI_MGMT, &hdev->flags))
>                mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
>                                                                rp->status);
> +
> +       hci_dev_unlock(hdev);
>  }
>
>  static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
> @@ -897,9 +918,13 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
>
>        BT_DBG("%s status 0x%x", hdev->name, rp->status);
>
> +       hci_dev_lock(hdev);
> +
>        if (test_bit(HCI_MGMT, &hdev->flags))
>                mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
>                                                                rp->status);
> +
> +       hci_dev_unlock(hdev);
>  }
>
>  static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
> @@ -909,8 +934,10 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
>
>        BT_DBG("%s status 0x%x", hdev->name, rp->status);
>
> +       hci_dev_lock(hdev);
>        mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
>                                                rp->randomizer, rp->status);
> +       hci_dev_unlock(hdev);
>  }
>
>  static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
> @@ -985,14 +1012,18 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>        if (status) {
>                hci_req_complete(hdev, HCI_OP_INQUIRY, status);
>                hci_conn_check_pending(hdev);
> +               hci_dev_lock(hdev);
>                if (test_bit(HCI_MGMT, &hdev->flags))
>                        mgmt_inquiry_failed(hdev, status);
> +               hci_dev_unlock(hdev);
>                return;
>        }
>
>        set_bit(HCI_INQUIRY, &hdev->flags);
>
> +       hci_dev_lock(hdev);
>        mgmt_discovering(hdev, 1);
> +       hci_dev_unlock(hdev);
>  }
>
>  static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
> @@ -1378,7 +1409,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
>        if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
>                return;
>
> +       hci_dev_lock(hdev);
>        mgmt_discovering(hdev, 0);
> +       hci_dev_unlock(hdev);
>  }
>
>  static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
> @@ -1572,7 +1605,9 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
>        BT_DBG("%s status %d", hdev->name, ev->status);
>
>        if (ev->status) {
> +               hci_dev_lock(hdev);
>                mgmt_disconnect_failed(hdev);
> +               hci_dev_unlock(hdev);
>                return;
>        }
>
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index be198f3..be4c3d0 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -1335,16 +1335,19 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
>  static void pairing_complete_cb(struct hci_conn *conn, u8 status)
>  {
>        struct pending_cmd *cmd;
> +       struct hci_dev *hdev = conn->hdev;
>
>        BT_DBG("status %u", status);
>
> +       hci_dev_lock_bh(hdev);
> +
>        cmd = find_pairing(conn);
> -       if (!cmd) {
> +       if (!cmd)
>                BT_DBG("Unable to find a pending command");
> -               return;
> -       }
> +       else
> +               pairing_complete(cmd, status);
>
> -       pairing_complete(cmd, status);
> +       hci_dev_unlock_bh(hdev);
>  }
>
>  static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
> @@ -2302,9 +2305,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
>                goto failed;
>        }
>
> -       hci_dev_lock_bh(hdev);
>        update_eir(hdev);
> -       hci_dev_unlock_bh(hdev);
>
>        err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev,
>                                                                sizeof(ev));
> --
> 1.7.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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