Merge branch 'bugfix/skip_memory_reordering_wpa2_semaphr' into 'master'

fix(esp_wifi): fixed stack corruption in WiFi tasks

Closes IDFGH-14617

See merge request espressif/esp-idf!36905
This commit is contained in:
Jiang Jiang Jian 2025-02-14 14:02:12 +08:00
commit 403cc24a47
4 changed files with 67 additions and 105 deletions

View File

@ -42,15 +42,11 @@ struct action_rx_param {
esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data) esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data)
{ {
dpp_event_t *evt = os_zalloc(sizeof(dpp_event_t)); dpp_event_t evt;
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
if (evt == NULL) { evt.id = evt_id;
ret = ESP_ERR_NO_MEM; evt.data = data;
goto end;
}
evt->id = evt_id;
evt->data = data;
if (s_dpp_api_lock) { if (s_dpp_api_lock) {
DPP_API_LOCK(); DPP_API_LOCK();
} else { } else {
@ -69,9 +65,6 @@ esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data)
return ret; return ret;
end: end:
if (evt) {
os_free(evt);
}
wpa_printf(MSG_ERROR, "DPP: Failed to send event %d to DPP task", evt_id); wpa_printf(MSG_ERROR, "DPP: Failed to send event %d to DPP task", evt_id);
return ret; return ret;
} }
@ -518,17 +511,16 @@ static esp_err_t esp_dpp_rx_action(struct action_rx_param *rx_param)
static void esp_dpp_task(void *pvParameters) static void esp_dpp_task(void *pvParameters)
{ {
dpp_event_t *evt; dpp_event_t evt;
bool task_del = false; bool task_del = false;
for (;;) { for (;;) {
if (os_queue_recv(s_dpp_evt_queue, &evt, OS_BLOCK) == TRUE) { if (os_queue_recv(s_dpp_evt_queue, &evt, OS_BLOCK) == TRUE) {
if (evt->id >= SIG_DPP_MAX) { if (evt.id >= SIG_DPP_MAX) {
os_free(evt);
continue; continue;
} }
switch (evt->id) { switch (evt.id) {
case SIG_DPP_DEL_TASK: case SIG_DPP_DEL_TASK:
struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL);
@ -549,7 +541,7 @@ static void esp_dpp_task(void *pvParameters)
break; break;
case SIG_DPP_BOOTSTRAP_GEN: { case SIG_DPP_BOOTSTRAP_GEN: {
char *command = (char *)evt->data; char *command = (char *)evt.data;
const char *uri; const char *uri;
s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command); s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command);
@ -561,7 +553,7 @@ static void esp_dpp_task(void *pvParameters)
break; break;
case SIG_DPP_RX_ACTION: { case SIG_DPP_RX_ACTION: {
esp_dpp_rx_action((struct action_rx_param *)evt->data); esp_dpp_rx_action((struct action_rx_param *)evt.data);
} }
break; break;
@ -588,7 +580,7 @@ static void esp_dpp_task(void *pvParameters)
break; break;
case SIG_DPP_START_NET_INTRO: { case SIG_DPP_START_NET_INTRO: {
esp_dpp_start_net_intro_protocol((uint8_t*)evt->data); esp_dpp_start_net_intro_protocol((uint8_t*)evt.data);
} }
break; break;
@ -605,8 +597,6 @@ static void esp_dpp_task(void *pvParameters)
break; break;
} }
os_free(evt);
if (task_del) { if (task_del) {
break; break;
} }

View File

@ -196,7 +196,7 @@ static void wpa2_rxq_deinit(void)
void wpa2_task(void *pvParameters) void wpa2_task(void *pvParameters)
{ {
ETSEvent *e; ETSEvent e;
struct eap_sm *sm = gEapSm; struct eap_sm *sm = gEapSm;
bool task_del = false; bool task_del = false;
@ -206,16 +206,16 @@ void wpa2_task(void *pvParameters)
for (;;) { for (;;) {
if (TRUE == os_queue_recv(s_wpa2_queue, &e, OS_BLOCK)) { if (TRUE == os_queue_recv(s_wpa2_queue, &e, OS_BLOCK)) {
if (e->sig < SIG_WPA2_MAX) { if (e.sig < SIG_WPA2_MAX) {
DATA_MUTEX_TAKE(); DATA_MUTEX_TAKE();
if (sm->wpa2_sig_cnt[e->sig]) { if (sm->wpa2_sig_cnt[e.sig]) {
sm->wpa2_sig_cnt[e->sig]--; sm->wpa2_sig_cnt[e.sig]--;
} else { } else {
wpa_printf(MSG_ERROR, "wpa2_task: invalid sig cnt, sig=%" PRId32 " cnt=%d", e->sig, sm->wpa2_sig_cnt[e->sig]); wpa_printf(MSG_ERROR, "wpa2_task: invalid sig cnt, sig=%" PRId32 " cnt=%d", e.sig, sm->wpa2_sig_cnt[e.sig]);
} }
DATA_MUTEX_GIVE(); DATA_MUTEX_GIVE();
} }
switch (e->sig) { switch (e.sig) {
case SIG_WPA2_TASK_DEL: case SIG_WPA2_TASK_DEL:
task_del = true; task_del = true;
break; break;
@ -235,12 +235,9 @@ void wpa2_task(void *pvParameters)
default: default:
break; break;
} }
os_free(e); if (task_del) {
} break;
}
if (task_del) {
break;
} else {
if (s_wifi_wpa2_sync_sem) { if (s_wifi_wpa2_sync_sem) {
wpa_printf(MSG_DEBUG, "EAP: wifi->EAP api completed"); wpa_printf(MSG_DEBUG, "EAP: wifi->EAP api completed");
os_semphr_give(s_wifi_wpa2_sync_sem); os_semphr_give(s_wifi_wpa2_sync_sem);
@ -268,6 +265,7 @@ void wpa2_task(void *pvParameters)
int wpa2_post(uint32_t sig, uint32_t par) int wpa2_post(uint32_t sig, uint32_t par)
{ {
struct eap_sm *sm = gEapSm; struct eap_sm *sm = gEapSm;
ETSEvent evt;
if (!sm) { if (!sm) {
return ESP_FAIL; return ESP_FAIL;
@ -277,28 +275,20 @@ int wpa2_post(uint32_t sig, uint32_t par)
if (sm->wpa2_sig_cnt[sig]) { if (sm->wpa2_sig_cnt[sig]) {
DATA_MUTEX_GIVE(); DATA_MUTEX_GIVE();
return ESP_OK; return ESP_OK;
}
sm->wpa2_sig_cnt[sig]++;
DATA_MUTEX_GIVE();
evt.sig = sig;
evt.par = par;
if (os_queue_send(s_wpa2_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
wpa_printf(MSG_ERROR, "EAP: Q S E");
return ESP_FAIL;
}
if (s_wifi_wpa2_sync_sem) {
os_semphr_take(s_wifi_wpa2_sync_sem, OS_BLOCK);
wpa_printf(MSG_DEBUG, "EAP: EAP api return, sm->state(%d)", sm->finish_state);
} else { } else {
ETSEvent *evt = (ETSEvent *)os_malloc(sizeof(ETSEvent)); wpa_printf(MSG_ERROR, "EAP: null wifi->EAP sync sem");
if (evt == NULL) {
wpa_printf(MSG_ERROR, "EAP: E N M");
DATA_MUTEX_GIVE();
return ESP_FAIL;
}
sm->wpa2_sig_cnt[sig]++;
DATA_MUTEX_GIVE();
evt->sig = sig;
evt->par = par;
if (os_queue_send(s_wpa2_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
wpa_printf(MSG_ERROR, "EAP: Q S E");
return ESP_FAIL;
} else {
if (s_wifi_wpa2_sync_sem) {
os_semphr_take(s_wifi_wpa2_sync_sem, OS_BLOCK);
wpa_printf(MSG_DEBUG, "EAP: EAP api return, sm->state(%d)", sm->finish_state);
} else {
wpa_printf(MSG_ERROR, "EAP: null wifi->EAP sync sem");
}
}
} }
return ESP_OK; return ESP_OK;
} }

View File

@ -412,38 +412,32 @@ SemaphoreHandle_t g_wpa3_hostap_auth_api_lock = NULL;
int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data) int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data)
{ {
wpa3_hostap_auth_event_t *evt = os_zalloc(sizeof(wpa3_hostap_auth_event_t)); wpa3_hostap_auth_event_t evt;
if (evt == NULL) {
return ESP_FAIL; evt.id = evt_id;
} evt.data = data;
evt->id = evt_id;
evt->data = data;
if (g_wpa3_hostap_auth_api_lock) { if (g_wpa3_hostap_auth_api_lock) {
WPA3_HOSTAP_AUTH_API_LOCK(); WPA3_HOSTAP_AUTH_API_LOCK();
if (g_wpa3_hostap_evt_queue == NULL) { if (g_wpa3_hostap_evt_queue == NULL) {
WPA3_HOSTAP_AUTH_API_UNLOCK(); WPA3_HOSTAP_AUTH_API_UNLOCK();
os_free(evt);
wpa_printf(MSG_DEBUG, "hostap evt queue NULL"); wpa_printf(MSG_DEBUG, "hostap evt queue NULL");
return ESP_FAIL; return ESP_FAIL;
} }
} else { } else {
os_free(evt);
wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found"); wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found");
return ESP_FAIL; return ESP_FAIL;
} }
if (evt->id == SIG_WPA3_RX_CONFIRM || evt->id == SIG_TASK_DEL) { if (evt.id == SIG_WPA3_RX_CONFIRM || evt.id == SIG_TASK_DEL) {
/* prioritising confirm for completing handshake for committed sta */ /* prioritising confirm for completing handshake for committed sta */
if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) { if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
WPA3_HOSTAP_AUTH_API_UNLOCK(); WPA3_HOSTAP_AUTH_API_UNLOCK();
wpa_printf(MSG_DEBUG, "failed to add msg to queue front"); wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
os_free(evt);
return ESP_FAIL; return ESP_FAIL;
} }
} else { } else {
if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) { if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
WPA3_HOSTAP_AUTH_API_UNLOCK(); WPA3_HOSTAP_AUTH_API_UNLOCK();
os_free(evt);
wpa_printf(MSG_DEBUG, "failed to send msg to queue"); wpa_printf(MSG_DEBUG, "failed to send msg to queue");
return ESP_FAIL; return ESP_FAIL;
} }
@ -562,18 +556,18 @@ done:
static void esp_wpa3_hostap_task(void *pvParameters) static void esp_wpa3_hostap_task(void *pvParameters)
{ {
wpa3_hostap_auth_event_t *evt; wpa3_hostap_auth_event_t evt;
bool task_del = false; bool task_del = false;
while (1) { while (1) {
if (os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY) == pdTRUE) { if (os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY) == pdTRUE) {
switch (evt->id) { switch (evt.id) {
case SIG_WPA3_RX_COMMIT: { case SIG_WPA3_RX_COMMIT: {
wpa3_process_rx_commit(evt); wpa3_process_rx_commit(&evt);
break; break;
} }
case SIG_WPA3_RX_CONFIRM: { case SIG_WPA3_RX_CONFIRM: {
wpa3_process_rx_confirm(evt); wpa3_process_rx_confirm(&evt);
break; break;
} }
case SIG_TASK_DEL: case SIG_TASK_DEL:
@ -582,7 +576,6 @@ static void esp_wpa3_hostap_task(void *pvParameters)
default: default:
break; break;
} }
os_free(evt);
if (task_del) { if (task_del) {
break; break;
@ -593,10 +586,9 @@ static void esp_wpa3_hostap_task(void *pvParameters)
while (items_in_queue--) { while (items_in_queue--) {
/* Free events posted to queue */ /* Free events posted to queue */
os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY); os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY);
if (evt->id == SIG_WPA3_RX_CONFIRM) { if (evt.id == SIG_WPA3_RX_CONFIRM) {
os_free((void *)evt->data); os_free((void *)evt.data);
} }
os_free(evt);
} }
os_queue_delete(g_wpa3_hostap_evt_queue); os_queue_delete(g_wpa3_hostap_evt_queue);
g_wpa3_hostap_evt_queue = NULL; g_wpa3_hostap_evt_queue = NULL;

View File

@ -119,7 +119,7 @@ static void wps_rxq_deinit(void)
#ifdef USE_WPS_TASK #ifdef USE_WPS_TASK
void wps_task(void *pvParameters) void wps_task(void *pvParameters)
{ {
ETSEvent *e; ETSEvent e;
wps_ioctl_param_t *param; wps_ioctl_param_t *param;
bool del_task = false; bool del_task = false;
@ -129,32 +129,32 @@ void wps_task(void *pvParameters)
for (;;) { for (;;) {
if (TRUE == os_queue_recv(s_wps_queue, &e, OS_BLOCK)) { if (TRUE == os_queue_recv(s_wps_queue, &e, OS_BLOCK)) {
if ((e->sig >= SIG_WPS_ENABLE) && (e->sig < SIG_WPS_NUM)) { if ((e.sig >= SIG_WPS_ENABLE) && (e.sig < SIG_WPS_NUM)) {
DATA_MUTEX_TAKE(); DATA_MUTEX_TAKE();
if (s_wps_sig_cnt[e->sig]) { if (s_wps_sig_cnt[e.sig]) {
s_wps_sig_cnt[e->sig]--; s_wps_sig_cnt[e.sig]--;
} else { } else {
wpa_printf(MSG_ERROR, "wpsT: invalid sig cnt, sig=%" PRId32 " cnt=%d", e->sig, s_wps_sig_cnt[e->sig]); wpa_printf(MSG_ERROR, "wpsT: invalid sig cnt, sig=%" PRId32 " cnt=%d", e.sig, s_wps_sig_cnt[e.sig]);
} }
DATA_MUTEX_GIVE(); DATA_MUTEX_GIVE();
} }
wpa_printf(MSG_DEBUG, "wpsT: rx sig=%" PRId32 "", e->sig); wpa_printf(MSG_DEBUG, "wpsT: rx sig=%" PRId32 "", e.sig);
switch (e->sig) { switch (e.sig) {
case SIG_WPS_ENABLE: case SIG_WPS_ENABLE:
case SIG_WPS_DISABLE: case SIG_WPS_DISABLE:
case SIG_WPS_START: case SIG_WPS_START:
param = (wps_ioctl_param_t *)e->par; param = (wps_ioctl_param_t *)e.par;
if (!param) { if (!param) {
wpa_printf(MSG_ERROR, "wpsT: invalid param sig=%" PRId32 "", e->sig); wpa_printf(MSG_ERROR, "wpsT: invalid param sig=%" PRId32 "", e.sig);
os_semphr_give(s_wps_api_sem); os_semphr_give(s_wps_api_sem);
break; break;
} }
if (e->sig == SIG_WPS_ENABLE) { if (e.sig == SIG_WPS_ENABLE) {
param->ret = wifi_wps_enable_internal((esp_wps_config_t *)(param->arg)); param->ret = wifi_wps_enable_internal((esp_wps_config_t *)(param->arg));
} else if (e->sig == SIG_WPS_DISABLE) { } else if (e.sig == SIG_WPS_DISABLE) {
DATA_MUTEX_TAKE(); DATA_MUTEX_TAKE();
param->ret = wifi_wps_disable_internal(); param->ret = wifi_wps_disable_internal();
del_task = true; del_task = true;
@ -198,10 +198,9 @@ void wps_task(void *pvParameters)
break; break;
default: default:
wpa_printf(MSG_ERROR, "wpsT: invalid sig=%" PRId32 "", e->sig); wpa_printf(MSG_ERROR, "wpsT: invalid sig=%" PRId32 "", e.sig);
break; break;
} }
os_free(e);
if (del_task) { if (del_task) {
wpa_printf(MSG_DEBUG, "wpsT: delete task"); wpa_printf(MSG_DEBUG, "wpsT: delete task");
@ -218,39 +217,30 @@ void wps_task(void *pvParameters)
int wps_post(uint32_t sig, uint32_t par) int wps_post(uint32_t sig, uint32_t par)
{ {
wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " cnt=%d", sig, s_wps_sig_cnt[sig]); wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " cnt=%d", sig, s_wps_sig_cnt[sig]);
ETSEvent evt;
DATA_MUTEX_TAKE();
if (!s_wps_task_hdl) { if (!s_wps_task_hdl) {
wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " failed as wps task has been deinited", sig); wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " failed as wps task has been deinited", sig);
DATA_MUTEX_GIVE();
return ESP_FAIL; return ESP_FAIL;
} }
DATA_MUTEX_TAKE();
if (s_wps_sig_cnt[sig]) { if (s_wps_sig_cnt[sig]) {
wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " processing", sig); wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " processing", sig);
DATA_MUTEX_GIVE(); DATA_MUTEX_GIVE();
return ESP_OK; return ESP_OK;
} else { }
ETSEvent *evt = (ETSEvent *)os_malloc(sizeof(ETSEvent));
if (evt == NULL) { s_wps_sig_cnt[sig]++;
wpa_printf(MSG_ERROR, "WPS: E N M"); evt.sig = sig;
DATA_MUTEX_GIVE(); evt.par = par;
return ESP_FAIL; DATA_MUTEX_GIVE();
}
s_wps_sig_cnt[sig]++; if (os_queue_send(s_wps_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
evt->sig = sig; wpa_printf(MSG_ERROR, "WPS: Q S E");
evt->par = par; DATA_MUTEX_TAKE();
s_wps_sig_cnt[sig]--;
DATA_MUTEX_GIVE(); DATA_MUTEX_GIVE();
return ESP_FAIL;
if (os_queue_send(s_wps_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
wpa_printf(MSG_ERROR, "WPS: Q S E");
DATA_MUTEX_TAKE();
s_wps_sig_cnt[sig]--;
DATA_MUTEX_GIVE();
return ESP_FAIL;
}
} }
return ESP_OK; return ESP_OK;
} }