From 145e565664c7979e21f691ee752ad459af6b12fb Mon Sep 17 00:00:00 2001 From: Huang Xiangping Date: Tue, 29 Sep 2026 11:56:49 +0800 Subject: [PATCH] wifi: cfg80211: process pending events before connect/disconnect requests cfg80211 reports connect results and disconnects through wdev->event_list, processed asynchronously by cfg80211_event_work(). The state that cfg80211_connect() and cfg80211_disconnect() reason about can therefore lag behind what the driver has already reported. cfg80211_disconnect() relies on that asynchronous processing on purpose: when the interface is connected it leaves wdev->u.client.ssid_len alone, expecting __cfg80211_disconnected() to clear it later: if (!wdev->connected) wdev->u.client.ssid_len = 0; If userspace reconnects before that deferred clear has run, cfg80211_connect() installs the new SSID and the queued EVENT_DISCONNECTED then wipes it again, together with wdev->connected, wdev->connect_keys and wdev->conn_owner_nlportid. The connection result of the new connection is subsequently processed with ssid_len == 0, so the BSS lookup in __cfg80211_connect_result() cannot match any BSS and WARN_ON(bss_not_found) triggers, dropping the connection result and leaving userspace waiting for a connection that is never reported. The same happens in cfg80211_roamed(). The zero ssid_len additionally defeats the -EALREADY and connection-owner checks of the following request, as both are skipped when ssid_len is zero. Fix this by draining the pending events before the connect and disconnect handlers inspect the interface state. Both run under the wiphy mutex, which cfg80211_process_rdev_events() requires, so no new lock ordering is introduced; this mirrors what cfg80211_change_iface() already does. Signed-off-by: Huang Xiangping Link: https://patch.msgid.link/20260929035649.33538-1-huangxiangping88@163.com Signed-off-by: Johannes Berg --- net/wireless/sme.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 458f72d8351a..85076f3b3355 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -1453,6 +1453,13 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, lockdep_assert_wiphy(wdev->wiphy); + /* + * Pending events may still change the state we're about to reason + * about (e.g. a deferred disconnect clearing ssid_len), so process + * them before looking at it. + */ + cfg80211_process_rdev_events(rdev); + /* * If we have an ssid_len, we're trying to connect or are * already connected, so reject a new SSID unless it's the @@ -1559,6 +1566,13 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, lockdep_assert_wiphy(wdev->wiphy); + /* + * Pending events may still change the state we're about to reason + * about (e.g. a deferred disconnect clearing ssid_len), so process + * them before looking at it. + */ + cfg80211_process_rdev_events(rdev); + kfree_sensitive(wdev->connect_keys); wdev->connect_keys = NULL;