From d841c78cf011f558f39a1c9bd429a68ffa72a4bb Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Thu, 2 Apr 2026 01:07:28 +0530 Subject: [PATCH] fix(esp_wifi): Fix concurrency for flags between wpa3 and Wi-Fi task --- .../esp_supplicant/src/esp_hostap.c | 4 ++-- .../esp_supplicant/src/esp_wpa3.c | 10 ++++---- components/wpa_supplicant/src/ap/ieee802_11.c | 10 ++++---- components/wpa_supplicant/src/ap/sta_info.c | 4 ++-- components/wpa_supplicant/src/ap/sta_info.h | 8 +++++-- components/wpa_supplicant/src/ap/wpa_auth.c | 24 +++++++++---------- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 600e3bfd492..65765edad8a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -595,7 +595,7 @@ static void ap_free_sta_timeout(void *ctx, void *data) HOSTAPD_STA_LIST_UNLOCK(hapd); ap_free_sta(hapd, sta); } else { - sta->remove_pending = true; + atomic_store(&sta->remove_pending, true); HOSTAPD_STA_LIST_UNLOCK(hapd); } goto done; @@ -650,7 +650,7 @@ bool wpa_ap_remove(u8* bssid) HOSTAPD_STA_LIST_UNLOCK(hapd); ap_free_sta(hapd, sta); } else { - sta->remove_pending = true; + atomic_store(&sta->remove_pending, true); HOSTAPD_STA_LIST_UNLOCK(hapd); } return true; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 6afb6d06a5a..895955d6d28 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -543,17 +543,17 @@ static void wpa3_process_rx_commit(wpa3_hostap_auth_event_t *evt) } if (sta->lock && os_semphr_take(sta->lock, 0)) { + atomic_store(&sta->sae_commit_processing, true); HOSTAPD_STA_LIST_UNLOCK(hapd); - sta->sae_commit_processing = true; ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status); - if (sta->remove_pending) { + if (atomic_load(&sta->remove_pending)) { ap_free_sta(hapd, sta); os_free(frm); return; } - sta->sae_commit_processing = false; + atomic_store(&sta->sae_commit_processing, false); os_semphr_give(sta->lock); uint16_t aid = 0; if (ret != WLAN_STATUS_SUCCESS && @@ -613,7 +613,7 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt) ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status); - if (sta->remove_pending) { + if (atomic_load(&sta->remove_pending)) { ap_free_sta(hapd, sta); goto done; } @@ -782,7 +782,7 @@ static int wpa3_hostap_handle_auth(u8 *buf, size_t len, u32 auth_transaction, u1 if (auth_transaction == SAE_MSG_COMMIT) { HOSTAPD_STA_LIST_LOCK(hapd); struct sta_info *sta = ap_get_sta_internal(hapd, bssid); - if (sta && sta->sae_commit_processing) { + if (sta && atomic_load(&sta->sae_commit_processing)) { HOSTAPD_STA_LIST_UNLOCK(hapd); return ESP_OK; } diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index 7aaff2ac966..99327c8acbb 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -159,7 +159,7 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, } #ifdef ESP_SUPPLICANT - if (sta->remove_pending) { + if (atomic_load(&sta->remove_pending)) { reply_res = -1; } else { reply_res = esp_send_sae_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1, @@ -185,7 +185,7 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd, } #ifdef ESP_SUPPLICANT - if (sta->remove_pending) { + if (atomic_load(&sta->remove_pending)) { reply_res = -1; wpabuf_free(data); } else { @@ -265,7 +265,7 @@ void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta) sta->flags |= WLAN_STA_AUTH; #ifdef ESP_SUPPLICANT - sta->sae_commit_processing = false; + atomic_store(&sta->sae_commit_processing, false); #endif /* ESP_SUPPLICANT */ sta->auth_alg = WLAN_AUTH_SAE; @@ -613,7 +613,7 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ; #ifdef ESP_SUPPLICANT - sta->sae_commit_processing = false; + atomic_store(&sta->sae_commit_processing, false); #endif /* ESP_SUPPLICANT */ goto reply; @@ -682,7 +682,7 @@ reply: data = wpabuf_alloc_copy(pos, 2); } #ifdef ESP_SUPPLICANT - if (!sta->remove_pending) { + if (!atomic_load(&sta->remove_pending)) { esp_send_sae_auth_reply(hapd, bssid, bssid, WLAN_AUTH_SAE, auth_transaction, resp, data ? wpabuf_head(data) : (u8 *) "", diff --git a/components/wpa_supplicant/src/ap/sta_info.c b/components/wpa_supplicant/src/ap/sta_info.c index fb3c8084d83..017fabb6305 100644 --- a/components/wpa_supplicant/src/ap/sta_info.c +++ b/components/wpa_supplicant/src/ap/sta_info.c @@ -239,8 +239,8 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) /* initialize STA info data */ os_memcpy(sta->addr, addr, ETH_ALEN); #ifdef CONFIG_SAE - sta->sae_commit_processing = false; - sta->remove_pending = false; + atomic_init(&sta->sae_commit_processing, false); + atomic_init(&sta->remove_pending, false); sta->lock = os_semphr_create(1, 1); if (!sta->lock) { wpa_printf(MSG_ERROR, "Failed to create sta->lock for " MACSTR, diff --git a/components/wpa_supplicant/src/ap/sta_info.h b/components/wpa_supplicant/src/ap/sta_info.h index 84a179dbd63..6117bac5528 100644 --- a/components/wpa_supplicant/src/ap/sta_info.h +++ b/components/wpa_supplicant/src/ap/sta_info.h @@ -9,6 +9,10 @@ #ifndef STA_INFO_H #define STA_INFO_H +#ifdef CONFIG_SAE +#include +#endif + /* STA flags */ #define WLAN_STA_AUTH BIT(0) #define WLAN_STA_ASSOC BIT(1) @@ -62,9 +66,9 @@ struct sta_info { #ifdef CONFIG_SAE void *lock; struct sae_data *sae; - volatile bool sae_commit_processing; /* halt queuing commit while we are + atomic_bool sae_commit_processing; /* halt queuing commit while we are * processing commit for that station */ - volatile bool remove_pending; /* Flag to indicate to free station when + atomic_bool remove_pending; /* Flag to indicate to free station when * whose mutex is taken by task */ struct wpabuf *sae_data; #endif /* CONFIG_SAE */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index af11c1002de..5eb27af0352 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -137,12 +137,9 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, } #if defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP) - /* wpa_auth_get_psk runs on the Wi-Fi task only, so these static buffers are safe */ #ifdef CONFIG_SAE + /* wpa_auth_get_psk runs on the Wi-Fi task only, so sae_pmk_copy is not shared with any other task. */ static u8 sae_pmk_copy[PMK_LEN]; -#endif -#ifdef CONFIG_OWE_SOFTAP - static u8 owe_pmk_copy[PMK_LEN_MAX]; #endif HOSTAPD_STA_LIST_LOCK(hapd); struct sta_info *sta = ap_get_sta_internal(hapd, addr); @@ -168,10 +165,8 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_OWE_SOFTAP if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta && sta->owe_pmk) { - size_t len = sta->owe_pmk_len > PMK_LEN_MAX ? PMK_LEN_MAX : sta->owe_pmk_len; - os_memcpy(owe_pmk_copy, sta->owe_pmk, len); HOSTAPD_STA_LIST_UNLOCK(hapd); - return owe_pmk_copy; + return sta->owe_pmk; } if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta) { @@ -179,15 +174,12 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, sa = wpa_auth_sta_get_pmksa(sta->wpa_sm); if (sa && sa->akmp == WPA_KEY_MGMT_OWE) { - size_t len = sa->pmk_len > PMK_LEN_MAX ? PMK_LEN_MAX : sa->pmk_len; - os_memcpy(owe_pmk_copy, sa->pmk, len); HOSTAPD_STA_LIST_UNLOCK(hapd); - return owe_pmk_copy; + return sa->pmk; } } - #endif /* CONFIG_OWE_SOFTAP */ - + HOSTAPD_STA_LIST_UNLOCK(hapd); #endif /* defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP) */ @@ -358,8 +350,14 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, if (sta_lk) { HOSTAPD_STA_LIST_LOCK(hapd); sta = ap_get_sta_internal(hapd, sta_mac); - if (sta && sta->lock == sta_lk) + if (sta && sta->lock == sta_lk) { os_semphr_give(sta_lk); + } else if (!sta) { + wpa_printf(MSG_DEBUG, + "WPA: sta->lock not released (STA " MACSTR + " gone); ap_free_sta released semaphore", + MAC2STR(sta_mac)); + } HOSTAPD_STA_LIST_UNLOCK(hapd); sta_lk = NULL; }