Skip to content

Commit

Permalink
Bluetooth: hci_sync: add lock to protect HCI_UNREGISTER
Browse files Browse the repository at this point in the history
[ Upstream commit 1857c19 ]

When the HCI_UNREGISTER flag is set, no jobs should be scheduled. Fix
potential race when HCI_UNREGISTER is set after the flag is tested in
hci_cmd_sync_queue.

Fixes: 0b94f26 ("Bluetooth: hci_sync: Fix queuing commands when HCI_UNREGISTER is set")
Signed-off-by: Zhengping Jiang <jiangzp@google.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Zhengping Jiang authored and gregkh committed Jun 14, 2023
1 parent 5f28540 commit 17aac12
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ struct hci_dev {
struct work_struct cmd_sync_work;
struct list_head cmd_sync_work_list;
struct mutex cmd_sync_work_lock;
struct mutex unregister_lock;
struct work_struct cmd_sync_cancel_work;
struct work_struct reenable_adv_work;

Expand Down
2 changes: 2 additions & 0 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2685,7 +2685,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
{
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);

mutex_lock(&hdev->unregister_lock);
hci_dev_set_flag(hdev, HCI_UNREGISTER);
mutex_unlock(&hdev->unregister_lock);

write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
Expand Down
20 changes: 14 additions & 6 deletions net/bluetooth/hci_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
INIT_LIST_HEAD(&hdev->cmd_sync_work_list);
mutex_init(&hdev->cmd_sync_work_lock);
mutex_init(&hdev->unregister_lock);

INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
INIT_WORK(&hdev->reenable_adv_work, reenable_adv);
Expand Down Expand Up @@ -688,14 +689,19 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
struct hci_cmd_sync_work_entry *entry;
int err = 0;

if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
return -ENODEV;
mutex_lock(&hdev->unregister_lock);
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
err = -ENODEV;
goto unlock;
}

entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;

if (!entry) {
err = -ENOMEM;
goto unlock;
}
entry->func = func;
entry->data = data;
entry->destroy = destroy;
Expand All @@ -706,7 +712,9 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,

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

return 0;
unlock:
mutex_unlock(&hdev->unregister_lock);
return err;
}
EXPORT_SYMBOL(hci_cmd_sync_queue);

Expand Down

0 comments on commit 17aac12

Please sign in to comment.