From 6c865a84ff729e3f94933b94241c9544a444aee2 Mon Sep 17 00:00:00 2001 From: xiehang Date: Fri, 5 Jul 2019 10:27:20 +0800 Subject: [PATCH] 1, Fix wps memory leak. 2, Add a queue to save wps rx eapol frame. 3, Add data lock protect wpa2_sig_cnt. 4, Add a queue to save wpa2 rx rapol frame. --- .../src/esp_supplicant/esp_wpa2.c | 89 +++++++++++++++++-- .../src/esp_supplicant/esp_wps.c | 77 +++++++++++++--- 2 files changed, 145 insertions(+), 21 deletions(-) diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c index a79502a1d..de7a3552a 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c @@ -48,6 +48,11 @@ #define WPA2_VERSION "v2.0" +#define DATA_MUTEX_TAKE() xSemaphoreTakeRecursive(s_wpa2_data_lock,portMAX_DELAY) +#define DATA_MUTEX_GIVE() xSemaphoreGiveRecursive(s_wpa2_data_lock) + +static void *s_wpa2_data_lock = NULL; + static struct eap_sm *gEapSm = NULL; static int eap_peer_sm_init(void); @@ -134,7 +139,48 @@ struct wpa2_rx_param { u8 sa[WPA_ADDR_LEN]; u8 *buf; int len; + STAILQ_ENTRY(wpa2_rx_param) bqentry; }; +static STAILQ_HEAD(, wpa2_rx_param) s_wpa2_rxq; + +static void wpa2_rxq_init(void) +{ + DATA_MUTEX_TAKE(); + STAILQ_INIT(&s_wpa2_rxq); + DATA_MUTEX_GIVE(); +} + +static void wpa2_rxq_enqueue(struct wpa2_rx_param *param) +{ + DATA_MUTEX_TAKE(); + STAILQ_INSERT_TAIL(&s_wpa2_rxq,param, bqentry); + DATA_MUTEX_GIVE(); +} + +static struct wpa2_rx_param * wpa2_rxq_dequeue(void) +{ + struct wpa2_rx_param *param = NULL; + DATA_MUTEX_TAKE(); + if ((param = STAILQ_FIRST(&s_wpa2_rxq)) != NULL) { + STAILQ_REMOVE_HEAD(&s_wpa2_rxq, bqentry); + STAILQ_NEXT(param,bqentry) = NULL; + } + DATA_MUTEX_GIVE(); + return param; +} + +static void wpa2_rxq_deinit(void) +{ + struct wpa2_rx_param *param = NULL; + DATA_MUTEX_TAKE(); + while ((param = STAILQ_FIRST(&s_wpa2_rxq)) != NULL) { + STAILQ_REMOVE_HEAD(&s_wpa2_rxq, bqentry); + STAILQ_NEXT(param,bqentry) = NULL; + os_free(param->buf); + os_free(param); + } + DATA_MUTEX_GIVE(); +} void wpa2_task(void *pvParameters ) { @@ -150,20 +196,26 @@ void wpa2_task(void *pvParameters ) for (;;) { if ( pdPASS == xQueueReceive(s_wpa2_queue, &e, portMAX_DELAY) ) { sig = e->sig; + if (e->sig < SIG_WPA2_MAX) { + DATA_MUTEX_TAKE(); + if(sm->wpa2_sig_cnt[e->sig]) { + sm->wpa2_sig_cnt[e->sig]--; + } else { + wpa_printf(MSG_ERROR, "wpa2_task: invalid sig cnt, sig=%d cnt=%d", e->sig, sm->wpa2_sig_cnt[e->sig]); + } + DATA_MUTEX_GIVE(); + } switch (e->sig) { case SIG_WPA2_TASK_DEL: task_del = true; break; case SIG_WPA2_START: - sm->wpa2_sig_cnt[e->sig]--; wpa2_start_eapol_internal(); break; case SIG_WPA2_RX: { - struct wpa2_rx_param *param; + struct wpa2_rx_param *param = NULL; - sm->wpa2_sig_cnt[e->sig]--; - param = (struct wpa2_rx_param *)(e->par); - if (param) { + while ((param = wpa2_rxq_dequeue()) != NULL){ wpa2_sm_rx_eapol_internal(param->sa, param->buf, param->len, param->bssid); os_free(param->buf); os_free(param); @@ -211,15 +263,19 @@ int wpa2_post(uint32_t sig, uint32_t par) return ESP_FAIL; } + DATA_MUTEX_TAKE(); if (sm->wpa2_sig_cnt[sig]) { + DATA_MUTEX_GIVE(); return ESP_OK; } else { ETSEvent *evt = (ETSEvent *)os_malloc(sizeof(ETSEvent)); if (evt == NULL) { wpa_printf(MSG_ERROR, "WPA2: E N M\n"); + DATA_MUTEX_GIVE(); return ESP_FAIL; } sm->wpa2_sig_cnt[sig]++; + DATA_MUTEX_GIVE(); evt->sig = sig; evt->par = par; if ( xQueueSend(s_wpa2_queue, &evt, 10 / portTICK_PERIOD_MS ) != pdPASS) { @@ -302,8 +358,8 @@ void wpa2_sm_free_eapol(u8 *buffer) { if (buffer != NULL) { buffer = buffer - sizeof(struct l2_ethhdr); + os_free(buffer); } - os_free(buffer); } @@ -480,7 +536,8 @@ static int wpa2_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len, uint8_t *bssid) param->len = len; memcpy(param->sa, src_addr, WPA_ADDR_LEN); - return wpa2_post(SIG_WPA2_RX, (uint32_t)param); + wpa2_rxq_enqueue(param); + return wpa2_post(SIG_WPA2_RX, 0); } #else @@ -656,6 +713,12 @@ static int eap_peer_sm_init(void) return ESP_ERR_NO_MEM; } + s_wpa2_data_lock = xSemaphoreCreateRecursiveMutex(); + if (!s_wpa2_data_lock) { + wpa_printf(MSG_ERROR, "wpa2 eap_peer_sm_init: failed to alloc data lock"); + return ESP_ERR_NO_MEM; + } + wpa2_set_eap_state(WPA2_ENT_EAP_STATE_NOT_START); sm->current_identifier = 0xff; esp_wifi_get_macaddr_internal(WIFI_IF_STA, sm->ownaddr); @@ -684,6 +747,7 @@ static int eap_peer_sm_init(void) return ESP_FAIL; } + wpa2_rxq_init(); gEapSm = sm; #ifdef USE_WPA2_TASK @@ -724,11 +788,22 @@ static void eap_peer_sm_deinit(void) #ifdef USE_WPA2_TASK wpa2_task_delete(0); #endif + + if (STAILQ_FIRST((&s_wpa2_rxq)) != NULL) { + wpa2_rxq_deinit(); + } + if (s_wifi_wpa2_sync_sem) { vSemaphoreDelete(s_wifi_wpa2_sync_sem); } s_wifi_wpa2_sync_sem = NULL; + if (s_wpa2_data_lock) { + vSemaphoreDelete(s_wpa2_data_lock); + s_wpa2_data_lock = NULL; + wpa_printf(MSG_DEBUG, "wpa2 eap_peer_sm_deinit: free data lock"); + } + os_free(sm); gEapSm = NULL; } diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wps.c b/components/wpa_supplicant/src/esp_supplicant/esp_wps.c index 03ed6e858..c666de305 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wps.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wps.c @@ -52,7 +52,9 @@ struct wps_rx_param { u8 sa[WPS_ADDR_LEN]; u8 *buf; int len; + STAILQ_ENTRY(wps_rx_param) bqentry; }; +static STAILQ_HEAD(,wps_rx_param) s_wps_rxq; typedef struct { void *arg; @@ -111,6 +113,45 @@ int wps_set_status(uint32_t status) return esp_wifi_set_wps_status_internal(status); } +static void wps_rxq_init(void) +{ + DATA_MUTEX_TAKE(); + STAILQ_INIT(&s_wps_rxq); + DATA_MUTEX_GIVE(); +} + +static void wps_rxq_enqueue(struct wps_rx_param *param) +{ + DATA_MUTEX_TAKE(); + STAILQ_INSERT_TAIL(&s_wps_rxq,param, bqentry); + DATA_MUTEX_GIVE(); +} + +static struct wps_rx_param * wps_rxq_dequeue(void) +{ + struct wps_rx_param *param = NULL; + DATA_MUTEX_TAKE(); + if ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) { + STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry); + STAILQ_NEXT(param,bqentry) = NULL; + } + DATA_MUTEX_GIVE(); + return param; +} + +static void wps_rxq_deinit(void) +{ + struct wps_rx_param *param = NULL; + DATA_MUTEX_TAKE(); + while ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) { + STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry); + STAILQ_NEXT(param,bqentry) = NULL; + os_free(param->buf); + os_free(param); + } + DATA_MUTEX_GIVE(); +} + #ifdef USE_WPS_TASK void wps_task(void *pvParameters ) { @@ -161,10 +202,8 @@ void wps_task(void *pvParameters ) break; case SIG_WPS_RX: { - struct wps_rx_param *param; - - param = (struct wps_rx_param *)(e->par); - if (param) { + struct wps_rx_param *param = NULL; + while ((param = wps_rxq_dequeue()) != NULL) { wps_sm_rx_eapol_internal(param->sa, param->buf, param->len); os_free(param->buf); os_free(param); @@ -311,9 +350,10 @@ u8 *wps_sm_alloc_eapol(struct wps_sm *sm, u8 type, void wps_sm_free_eapol(u8 *buffer) { - buffer = buffer - sizeof(struct l2_ethhdr); - os_free(buffer); - + if (buffer != NULL) { + buffer = buffer - sizeof(struct l2_ethhdr); + os_free(buffer); + } } @@ -658,6 +698,7 @@ int wps_send_frag_ack(u8 id) } ret = wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + wps_sm_free_eapol(buf); if (ret) { ret = ESP_ERR_NO_MEM; goto _err; @@ -835,6 +876,7 @@ int wps_send_wps_mX_rsp(u8 id) } ret = wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + wps_sm_free_eapol(buf); if (ret) { ret = ESP_FAIL; goto _err; @@ -1055,7 +1097,8 @@ int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) param->len = len; memcpy(param->sa, src_addr, WPS_ADDR_LEN); - return wps_post(SIG_WPS_RX, (uint32_t)param); + wps_rxq_enqueue(param); + return wps_post(SIG_WPS_RX, 0); } #else return wps_sm_rx_eapol_internal(src_addr, buf, len); @@ -1828,12 +1871,6 @@ int wps_task_deinit(void) { wpa_printf(MSG_DEBUG, "wps task deinit"); - if (s_wps_data_lock) { - vSemaphoreDelete(s_wps_data_lock); - s_wps_data_lock = NULL; - wpa_printf(MSG_DEBUG, "wps task deinit: free data lock"); - } - if (s_wps_api_sem) { vSemaphoreDelete(s_wps_api_sem); s_wps_api_sem = NULL; @@ -1858,6 +1895,16 @@ int wps_task_deinit(void) wpa_printf(MSG_DEBUG, "wps task deinit: free task"); } + if (STAILQ_FIRST(&s_wps_rxq) != NULL){ + wps_rxq_deinit(); + } + + if (s_wps_data_lock) { + vSemaphoreDelete(s_wps_data_lock); + s_wps_data_lock = NULL; + wpa_printf(MSG_DEBUG, "wps task deinit: free data lock"); + } + return ESP_OK; } @@ -1894,6 +1941,8 @@ int wps_task_init(void) goto _wps_no_mem; } + wps_rxq_init(); + ret = xTaskCreate(wps_task, "wpsT", WPS_TASK_STACK_SIZE, NULL, 2, &s_wps_task_hdl); if (pdPASS != ret) { wpa_printf(MSG_ERROR, "wps enable: failed to create task");