Skip to content

Commit f53e1c9

Browse files
committed
Bluetooth: MGMT: Fix possible crash on mgmt_index_removed
If mgmt_index_removed is called while there are commands queued on cmd_sync it could lead to crashes like the bellow trace: 0x0000053D: __list_del_entry_valid_or_report+0x98/0xdc 0x0000053D: mgmt_pending_remove+0x18/0x58 [bluetooth] 0x0000053E: mgmt_remove_adv_monitor_complete+0x80/0x108 [bluetooth] 0x0000053E: hci_cmd_sync_work+0xbc/0x164 [bluetooth] So while handling mgmt_index_removed this attempts to dequeue commands passed as user_data to cmd_sync. Fixes: 7cf5c29 ("Bluetooth: hci_sync: Refactor remove Adv Monitor") Reported-by: jiaymao <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent d505d35 commit f53e1c9

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

net/bluetooth/mgmt.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,10 +1453,15 @@ static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
14531453

14541454
static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
14551455
{
1456-
if (cmd->cmd_complete) {
1457-
u8 *status = data;
1456+
struct cmd_lookup *match = data;
1457+
1458+
/* dequeue cmd_sync entries using cmd as data as that is about to be
1459+
* removed/freed.
1460+
*/
1461+
hci_cmd_sync_dequeue(match->hdev, NULL, cmd, NULL);
14581462

1459-
cmd->cmd_complete(cmd, *status);
1463+
if (cmd->cmd_complete) {
1464+
cmd->cmd_complete(cmd, match->mgmt_status);
14601465
mgmt_pending_remove(cmd);
14611466

14621467
return;
@@ -9394,12 +9399,12 @@ void mgmt_index_added(struct hci_dev *hdev)
93949399
void mgmt_index_removed(struct hci_dev *hdev)
93959400
{
93969401
struct mgmt_ev_ext_index ev;
9397-
u8 status = MGMT_STATUS_INVALID_INDEX;
9402+
struct cmd_lookup match = { NULL, hdev, MGMT_STATUS_INVALID_INDEX };
93989403

93999404
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
94009405
return;
94019406

9402-
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
9407+
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
94039408

94049409
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
94059410
mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0,
@@ -9450,7 +9455,7 @@ void mgmt_power_on(struct hci_dev *hdev, int err)
94509455
void __mgmt_power_off(struct hci_dev *hdev)
94519456
{
94529457
struct cmd_lookup match = { NULL, hdev };
9453-
u8 status, zero_cod[] = { 0, 0, 0 };
9458+
u8 zero_cod[] = { 0, 0, 0 };
94549459

94559460
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
94569461

@@ -9462,11 +9467,11 @@ void __mgmt_power_off(struct hci_dev *hdev)
94629467
* status responses.
94639468
*/
94649469
if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
9465-
status = MGMT_STATUS_INVALID_INDEX;
9470+
match.mgmt_status = MGMT_STATUS_INVALID_INDEX;
94669471
else
9467-
status = MGMT_STATUS_NOT_POWERED;
9472+
match.mgmt_status = MGMT_STATUS_NOT_POWERED;
94689473

9469-
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
9474+
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
94709475

94719476
if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
94729477
mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,

0 commit comments

Comments
 (0)