Skip to content

Commit d883a46

Browse files
committed
Bluetooth: hci_sync: Only allow hci_cmd_sync_queue if running
This makes sure hci_cmd_sync_queue only queue new work if HCI_RUNNING has been set otherwise there is a risk of commands being sent while turning off. Because hci_cmd_sync_queue can no longer queue work while HCI_RUNNING is not set it cannot be used to power on adapters so instead hci_cmd_sync_submit is introduced which bypass the HCI_RUNNING check, so it behaves like the old implementation. Link: https://lore.kernel.org/all/CAB4PzUpDMvdc8j2MdeSAy1KkAE-D3woprCwAdYWeOc-3v3c9Sw@mail.gmail.com/ Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 20981ce commit d883a46

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

include/net/bluetooth/hci_sync.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev);
4141
void hci_cmd_sync_cancel(struct hci_dev *hdev, int err);
4242
void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err);
4343

44+
int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
45+
void *data, hci_cmd_sync_work_destroy_t destroy);
4446
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
4547
void *data, hci_cmd_sync_work_destroy_t destroy);
4648

net/bluetooth/hci_sync.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,12 @@ void hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
684684
}
685685
EXPORT_SYMBOL(hci_cmd_sync_cancel);
686686

687-
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
688-
void *data, hci_cmd_sync_work_destroy_t destroy)
687+
/* Submit HCI command to be run in as cmd_sync_work:
688+
*
689+
* - hdev must _not_ be unregistered
690+
*/
691+
int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
692+
void *data, hci_cmd_sync_work_destroy_t destroy)
689693
{
690694
struct hci_cmd_sync_work_entry *entry;
691695

@@ -708,6 +712,23 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
708712

709713
return 0;
710714
}
715+
EXPORT_SYMBOL(hci_cmd_sync_submit);
716+
717+
/* Queue HCI command:
718+
*
719+
* - hdev must be running
720+
*/
721+
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
722+
void *data, hci_cmd_sync_work_destroy_t destroy)
723+
{
724+
/* Only queue command if hdev is running which means it had been opened
725+
* and is either on init phase or is already up.
726+
*/
727+
if (!test_bit(HCI_RUNNING, &hdev->flags))
728+
return -ENETDOWN;
729+
730+
return hci_cmd_sync_submit(hdev, func, data, destroy);
731+
}
711732
EXPORT_SYMBOL(hci_cmd_sync_queue);
712733

713734
int hci_update_eir_sync(struct hci_dev *hdev)

net/bluetooth/mgmt.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,11 +1400,15 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
14001400
}
14011401

14021402
/* Cancel potentially blocking sync operation before power off */
1403-
if (cp->val == 0x00)
1403+
if (cp->val == 0x00) {
14041404
__hci_cmd_sync_cancel(hdev, -EHOSTDOWN);
1405-
1406-
err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd,
1407-
mgmt_set_powered_complete);
1405+
err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd,
1406+
mgmt_set_powered_complete);
1407+
} else {
1408+
/* Use hci_cmd_sync_submit since hdev might not be running */
1409+
err = hci_cmd_sync_submit(hdev, set_powered_sync, cmd,
1410+
mgmt_set_powered_complete);
1411+
}
14081412

14091413
if (err < 0)
14101414
mgmt_pending_remove(cmd);

0 commit comments

Comments
 (0)