diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index bab1e3d7452a..492723a22e68 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -345,6 +345,7 @@ enum { HCI_UP, HCI_INIT, HCI_RUNNING, + HCI_CLOSING, HCI_PSCAN, HCI_ISCAN, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 629c302f7407..95f55cfb6da6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -501,12 +501,16 @@ int hci_dev_close(__u16 dev) goto done; } + set_bit(HCI_CLOSING, &hdev->flags); + cancel_work_sync(&hdev->power_on); if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) cancel_delayed_work(&hdev->power_off); err = hci_dev_do_close(hdev); + if (unlikely(err)) + clear_bit(HCI_CLOSING, &hdev->flags); done: hci_dev_put(hdev); return err; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 2272e1849ebd..ff43718822d4 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1671,6 +1671,11 @@ static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, goto done; } + if (unlikely(test_bit(HCI_CLOSING, &hdev->flags))) { + err = -ENODEV; + goto done; + } + if (hci_dev_test_flag(hdev, HCI_SETUP) || hci_dev_test_flag(hdev, HCI_CONFIG) || hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {