Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
syzbot is reporting that calling hci_release_dev() from hci_error_reset() due to hci_dev_put() from hci_error_reset() can cause deadlock at destroy_workqueue(), for hci_error_reset() is called from hdev->req_workqueue which destroy_workqueue() needs to flush. We need to make sure that hdev->{rx_work,cmd_work,tx_work} which are queued into hdev->workqueue and hdev->{power_on,error_reset} which are queued into hdev->req_workqueue are no longer running by the moment destroy_workqueue(hdev->workqueue); destroy_workqueue(hdev->req_workqueue); are called from hci_release_dev(). Call cancel_work_sync() on these work items from hci_unregister_dev() as soon as hdev->list is removed from hci_dev_list. Reported-by: syzbot <syzbot+da0a9c9721e36db712e8@syzkaller.appspotmail.com> Closes: https://syzkaller.appspot.com/bug?extid=da0a9c9721e36db712e8 Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
88e72239ea
commit
0d151a1037
@ -2751,7 +2751,11 @@ void hci_unregister_dev(struct hci_dev *hdev)
|
|||||||
list_del(&hdev->list);
|
list_del(&hdev->list);
|
||||||
write_unlock(&hci_dev_list_lock);
|
write_unlock(&hci_dev_list_lock);
|
||||||
|
|
||||||
|
cancel_work_sync(&hdev->rx_work);
|
||||||
|
cancel_work_sync(&hdev->cmd_work);
|
||||||
|
cancel_work_sync(&hdev->tx_work);
|
||||||
cancel_work_sync(&hdev->power_on);
|
cancel_work_sync(&hdev->power_on);
|
||||||
|
cancel_work_sync(&hdev->error_reset);
|
||||||
|
|
||||||
hci_cmd_sync_clear(hdev);
|
hci_cmd_sync_clear(hdev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user