Skip to content

Commit 51dd39c

Browse files
committed
Bluetooth: hci_sync: add lock to protect HCI_UNREGISTER
jira VULN-50081 jira VULN-50082 cve-bf CVE-2022-49136 commit-author Zhengping Jiang <[email protected]> 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 <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]> (cherry picked from commit 1857c19) Signed-off-by: Jonathan Maple <[email protected]>
1 parent e75b49c commit 51dd39c

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ struct hci_dev {
483483
struct work_struct cmd_sync_work;
484484
struct list_head cmd_sync_work_list;
485485
struct mutex cmd_sync_work_lock;
486+
struct mutex unregister_lock;
486487
struct work_struct cmd_sync_cancel_work;
487488

488489
__u16 discov_timeout;

net/bluetooth/hci_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,7 +2669,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
26692669
{
26702670
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
26712671

2672+
mutex_lock(&hdev->unregister_lock);
26722673
hci_dev_set_flag(hdev, HCI_UNREGISTER);
2674+
mutex_unlock(&hdev->unregister_lock);
26732675

26742676
write_lock(&hci_dev_list_lock);
26752677
list_del(&hdev->list);

net/bluetooth/hci_sync.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
326326
INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
327327
INIT_LIST_HEAD(&hdev->cmd_sync_work_list);
328328
mutex_init(&hdev->cmd_sync_work_lock);
329+
mutex_init(&hdev->unregister_lock);
329330

330331
INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
331332
}
@@ -378,14 +379,19 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
378379
void *data, hci_cmd_sync_work_destroy_t destroy)
379380
{
380381
struct hci_cmd_sync_work_entry *entry;
382+
int err = 0;
381383

382-
if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
383-
return -ENODEV;
384+
mutex_lock(&hdev->unregister_lock);
385+
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
386+
err = -ENODEV;
387+
goto unlock;
388+
}
384389

385390
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
386-
if (!entry)
387-
return -ENOMEM;
388-
391+
if (!entry) {
392+
err = -ENOMEM;
393+
goto unlock;
394+
}
389395
entry->func = func;
390396
entry->data = data;
391397
entry->destroy = destroy;
@@ -396,7 +402,9 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
396402

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

399-
return 0;
405+
unlock:
406+
mutex_unlock(&hdev->unregister_lock);
407+
return err;
400408
}
401409
EXPORT_SYMBOL(hci_cmd_sync_queue);
402410

0 commit comments

Comments
 (0)