mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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 <huangxiangping88@163.com> Link: https://patch.msgid.link/20260929035649.33538-1-huangxiangping88@163.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
34f93ba0bc
commit
145e565664
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user