From: Jouni Malinen Date: Sun, 25 Jan 2026 18:17:24 +0000 (+0200) Subject: AP MLD: Clear wpa_sm entries for all STAs when freeing a wpa_sm X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f6124cdbf2667eb2b56b8c7e275135007815971;p=thirdparty%2Fhostap.git AP MLD: Clear wpa_sm entries for all STAs when freeing a wpa_sm While the use of clear_wpa_sm_for_each_partner_link() is supposed to handle this, add a more robust approach for making sure no pointers to freed wpa_sm instances are left behind regardless of how the non-AP MLD partner STA entries are handled in cases where the same MAC address is used in ML and non-ML cases. Signed-off-by: Jouni Malinen --- diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 47e5d3a5d..1988d3c8a 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3595,7 +3595,10 @@ static void handle_auth(struct hostapd_data *hapd, if ((!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) && sta->wpa_sm) { - wpa_auth_sta_deinit(sta->wpa_sm); + struct wpa_state_machine *sm = sta->wpa_sm; + + clear_wpa_sm_for_all_sta(hapd, sm); + wpa_auth_sta_deinit(sm); sta->wpa_sm = NULL; clear_wpa_sm_for_each_partner_link(hapd, sta); } @@ -4927,7 +4930,10 @@ skip_wpa_ies: out: if (resp != WLAN_STATUS_SUCCESS || assoc_wpa_sm) { - wpa_auth_sta_deinit(sta->wpa_sm); + struct wpa_state_machine *sm = sta->wpa_sm; + + clear_wpa_sm_for_all_sta(hapd, sm); + wpa_auth_sta_deinit(sm); /* Only keep a reference to the main wpa_sm and drop the * per-link instance. diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 6d2bd5f1c..0fea6c4fb 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -247,6 +247,25 @@ void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, set_wpa_sm_for_each_partner_link(hapd, psta, NULL); } + +void clear_wpa_sm_for_all_sta(struct hostapd_data *hapd, + struct wpa_state_machine *wpa_sm) +{ + struct hostapd_data *lhapd; + + if (!hapd->mld) + return; + + for_each_mld_link(lhapd, hapd) { + struct sta_info *sta; + + for (sta = lhapd->sta_list; sta; sta = sta->next) { + if (sta->wpa_sm == wpa_sm) + sta->wpa_sm = NULL; + } + } +} + #endif /* CONFIG_IEEE80211BE */ diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 4f41f7028..886f9129b 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -443,5 +443,7 @@ void set_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, struct sta_info *psta, void *wpa_sm); void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, struct sta_info *psta); +void clear_wpa_sm_for_all_sta(struct hostapd_data *hapd, + struct wpa_state_machine *wpa_sm); #endif /* STA_INFO_H */