mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: 7cf5c2978f ("Bluetooth: hci_sync: Refactor remove Adv Monitor")
Reported-by: jiaymao <quic_jiaymao@quicinc.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
			
			
This commit is contained in:
		
							parent
							
								
									d505d3593b
								
							
						
					
					
						commit
						f53e1c9c72
					
				
					 1 changed files with 14 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -1453,10 +1453,15 @@ static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
 | 
			
		|||
 | 
			
		||||
static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
 | 
			
		||||
{
 | 
			
		||||
	if (cmd->cmd_complete) {
 | 
			
		||||
		u8 *status = data;
 | 
			
		||||
	struct cmd_lookup *match = data;
 | 
			
		||||
 | 
			
		||||
		cmd->cmd_complete(cmd, *status);
 | 
			
		||||
	/* dequeue cmd_sync entries using cmd as data as that is about to be
 | 
			
		||||
	 * removed/freed.
 | 
			
		||||
	 */
 | 
			
		||||
	hci_cmd_sync_dequeue(match->hdev, NULL, cmd, NULL);
 | 
			
		||||
 | 
			
		||||
	if (cmd->cmd_complete) {
 | 
			
		||||
		cmd->cmd_complete(cmd, match->mgmt_status);
 | 
			
		||||
		mgmt_pending_remove(cmd);
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -9394,12 +9399,12 @@ void mgmt_index_added(struct hci_dev *hdev)
 | 
			
		|||
void mgmt_index_removed(struct hci_dev *hdev)
 | 
			
		||||
{
 | 
			
		||||
	struct mgmt_ev_ext_index ev;
 | 
			
		||||
	u8 status = MGMT_STATUS_INVALID_INDEX;
 | 
			
		||||
	struct cmd_lookup match = { NULL, hdev, MGMT_STATUS_INVALID_INDEX };
 | 
			
		||||
 | 
			
		||||
	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
 | 
			
		||||
	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
 | 
			
		||||
 | 
			
		||||
	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
 | 
			
		||||
		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)
 | 
			
		|||
void __mgmt_power_off(struct hci_dev *hdev)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_lookup match = { NULL, hdev };
 | 
			
		||||
	u8 status, zero_cod[] = { 0, 0, 0 };
 | 
			
		||||
	u8 zero_cod[] = { 0, 0, 0 };
 | 
			
		||||
 | 
			
		||||
	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -9462,11 +9467,11 @@ void __mgmt_power_off(struct hci_dev *hdev)
 | 
			
		|||
	 * status responses.
 | 
			
		||||
	 */
 | 
			
		||||
	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
 | 
			
		||||
		status = MGMT_STATUS_INVALID_INDEX;
 | 
			
		||||
		match.mgmt_status = MGMT_STATUS_INVALID_INDEX;
 | 
			
		||||
	else
 | 
			
		||||
		status = MGMT_STATUS_NOT_POWERED;
 | 
			
		||||
		match.mgmt_status = MGMT_STATUS_NOT_POWERED;
 | 
			
		||||
 | 
			
		||||
	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
 | 
			
		||||
	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
 | 
			
		||||
 | 
			
		||||
	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
 | 
			
		||||
		mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue