Commit 00fdebbb authored by Hyunwoo Kim's avatar Hyunwoo Kim Committed by Luiz Augusto von Dentz
Browse files

Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del()



l2cap_conn_del() calls cancel_delayed_work_sync() for both info_timer
and id_addr_timer while holding conn->lock. However, the work functions
l2cap_info_timeout() and l2cap_conn_update_id_addr() both acquire
conn->lock, creating a potential AB-BA deadlock if the work is already
executing when l2cap_conn_del() takes the lock.

Move the work cancellations before acquiring conn->lock and use
disable_delayed_work_sync() to additionally prevent the works from
being rearmed after cancellation, consistent with the pattern used in
hci_conn_del().

Fixes: ab4eedb7 ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del")
Signed-off-by: default avatarHyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 94d8e6fe
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -1771,6 +1771,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)

	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);

	disable_delayed_work_sync(&conn->info_timer);
	disable_delayed_work_sync(&conn->id_addr_timer);

	mutex_lock(&conn->lock);

	kfree_skb(conn->rx_skb);
@@ -1786,8 +1789,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)

	ida_destroy(&conn->tx_ida);

	cancel_delayed_work_sync(&conn->id_addr_timer);

	l2cap_unregister_all_users(conn);

	/* Force the connection to be immediately dropped */
@@ -1806,9 +1807,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
		l2cap_chan_put(chan);
	}

	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
		cancel_delayed_work_sync(&conn->info_timer);

	hci_chan_del(conn->hchan);
	conn->hchan = NULL;