Skip to content

Commit 02d6704

Browse files
committed
fix(wpa_supplicant): Improve execution flow for WPS registrar public APIs
Make sure that WPS registrar public APIs do not modify supplicant data in application task context. Execute API functionlity in eloop context to prevent protential race conditions.
1 parent e1502fb commit 02d6704

File tree

3 files changed

+173
-73
lines changed

3 files changed

+173
-73
lines changed

components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c

Lines changed: 156 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -26,12 +26,15 @@
2626
#include "ap/hostapd.h"
2727
#include "ap/ap_config.h"
2828
#include "ap/wps_hostapd.h"
29+
#include "utils/eloop.h"
2930

3031
extern struct wps_sm *gWpsSm;
3132
extern void *s_wps_api_lock;
3233
extern void *s_wps_api_sem;
3334
extern bool s_wps_enabled;
3435

36+
static int wps_reg_eloop_post_block(uint32_t sig, void *arg);
37+
3538
static int wifi_ap_wps_init(const esp_wps_config_t *config)
3639
{
3740
struct wps_sm *sm = NULL;
@@ -138,41 +141,8 @@ int wifi_ap_wps_deinit(void)
138141
return ESP_OK;
139142
}
140143

141-
int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
142-
{
143-
int ret = 0;
144-
145-
wpa_printf(MSG_DEBUG, "ESP WPS crypto initialize!");
146-
if (config->wps_type == WPS_TYPE_DISABLE) {
147-
wpa_printf(MSG_ERROR, "wps enable: invalid wps type");
148-
return ESP_ERR_WIFI_WPS_TYPE;
149-
}
150-
151-
wpa_printf(MSG_DEBUG, "Set factory information.");
152-
ret = wps_set_factory_info(config);
153-
if (ret != 0) {
154-
return ret;
155-
}
156-
157-
wpa_printf(MSG_INFO, "wifi_wps_enable");
158-
159-
wps_set_type(config->wps_type);
160-
wps_set_status(WPS_STATUS_DISABLE);
161-
162-
ret = wifi_ap_wps_init(config);
163-
164-
if (ret != 0) {
165-
wps_set_type(WPS_STATUS_DISABLE);
166-
wps_set_status(WPS_STATUS_DISABLE);
167-
return ESP_FAIL;
168-
}
169-
170-
return ESP_OK;
171-
}
172-
173-
int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
144+
static int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
174145
{
175-
int ret = ESP_OK;
176146
struct wps_sm *sm = gWpsSm;
177147
wifi_mode_t mode = WIFI_MODE_NULL;
178148

@@ -181,7 +151,11 @@ int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
181151
return ESP_ERR_WIFI_STATE;
182152
}
183153

184-
ret = esp_wifi_get_mode(&mode);
154+
if (esp_wifi_get_mode(&mode) != ESP_OK) {
155+
wpa_printf(MSG_ERROR, "wps enable: unable to get current wifi mode");
156+
return ESP_FAIL;
157+
}
158+
185159
if (mode != WIFI_MODE_AP && mode != WIFI_MODE_APSTA) {
186160
wpa_printf(MSG_ERROR, "wps enable: mode=%d does not include AP", mode);
187161
return ESP_ERR_WIFI_MODE;
@@ -192,58 +166,106 @@ int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
192166
return ESP_ERR_WIFI_MODE;
193167
}
194168

195-
API_MUTEX_TAKE();
196169
if (s_wps_enabled) {
197170
if (sm && os_memcmp(sm->identity, WSC_ID_ENROLLEE, sm->identity_len) == 0) {
198171
wpa_printf(MSG_ERROR, "wps enable: wps enrollee already enabled cannot enable wpsreg");
199-
ret = ESP_ERR_WIFI_MODE;
172+
return ESP_ERR_WIFI_MODE;
200173
} else {
201174
wpa_printf(MSG_DEBUG, "wps enable: already enabled");
202-
ret = ESP_OK;
175+
return ESP_OK;
203176
}
204-
API_MUTEX_GIVE();
205-
return ret;
206177
}
207178

208-
ret = wifi_ap_wps_enable_internal(config);
179+
if (config->wps_type == WPS_TYPE_DISABLE) {
180+
wpa_printf(MSG_ERROR, "wps enable: invalid wps type");
181+
return ESP_ERR_WIFI_WPS_TYPE;
182+
}
183+
184+
wpa_printf(MSG_DEBUG, "Set factory information.");
185+
if (wps_set_factory_info(config) != ESP_OK) {
186+
return ESP_FAIL;
187+
}
188+
189+
190+
if (wps_set_type(config->wps_type) != ESP_OK) {
191+
goto _err;
192+
}
193+
194+
if (wps_set_status(WPS_STATUS_DISABLE) != ESP_OK) {
195+
goto _err;
196+
}
197+
198+
if (wifi_ap_wps_init(config) != ESP_OK) {
199+
goto _err;
200+
}
201+
202+
wpa_printf(MSG_INFO, "wifi_wps_enable");
209203
s_wps_enabled = true;
204+
return ESP_OK;
205+
206+
_err:
207+
wpa_printf(MSG_ERROR, "failure in wifi_wps_enable");
208+
wps_set_type(WPS_TYPE_DISABLE);
209+
wps_set_status(WPS_STATUS_DISABLE);
210+
211+
return ESP_FAIL;
212+
}
213+
214+
int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
215+
{
216+
int ret = ESP_OK;
217+
218+
API_MUTEX_TAKE();
219+
ret = wps_reg_eloop_post_block(SIG_WPS_REG_ENABLE, (void *) config);
210220
API_MUTEX_GIVE();
211221
return ret;
212222
}
213223

214-
int esp_wifi_ap_wps_disable(void)
224+
static int wifi_ap_wps_disable_internal(void)
215225
{
216-
int ret = 0;
217226
struct wps_sm *sm = gWpsSm;
218227

219228
if (sm && os_memcmp(sm->identity, WSC_ID_ENROLLEE, sm->identity_len) == 0) {
220229
return ESP_ERR_WIFI_MODE;
221230
}
222231

223-
API_MUTEX_TAKE();
224-
225232
if (!s_wps_enabled) {
226233
wpa_printf(MSG_DEBUG, "wps disable: already disabled");
227-
API_MUTEX_GIVE();
228234
return ESP_OK;
229235
}
230236

231237
wpa_printf(MSG_INFO, "wifi_wps_disable");
232-
wps_set_type(WPS_TYPE_DISABLE);
233-
wps_set_status(WPS_STATUS_DISABLE);
238+
if (wps_set_type(WPS_TYPE_DISABLE) != ESP_OK) {
239+
goto _err;
240+
}
234241

235-
wifi_ap_wps_deinit();
242+
if (wps_set_status(WPS_STATUS_DISABLE) != ESP_OK) {
243+
goto _err;
244+
}
236245

237-
if (ESP_OK != ret) {
238-
wpa_printf(MSG_ERROR, "wps disable: failed to disable wps, ret=%d", ret);
246+
if (wifi_ap_wps_deinit() != ESP_OK) {
247+
goto _err;
239248
}
240249

250+
241251
s_wps_enabled = false;
242-
API_MUTEX_GIVE();
243252
return ESP_OK;
253+
254+
_err:
255+
wpa_printf(MSG_ERROR, "wps disable: failed to disable wps");
256+
return ESP_FAIL;
244257
}
245258

246-
int esp_wifi_ap_wps_start(const unsigned char *pin)
259+
int esp_wifi_ap_wps_disable(void)
260+
{
261+
int ret = ESP_FAIL;
262+
API_MUTEX_TAKE();
263+
ret = wps_reg_eloop_post_block(SIG_WPS_REG_DISABLE, NULL);
264+
API_MUTEX_GIVE();
265+
return ret;
266+
}
267+
268+
static int wifi_ap_wps_start_internal(const unsigned char *pin)
247269
{
248270
wifi_mode_t mode = WIFI_MODE_NULL;
249271

@@ -253,37 +275,107 @@ int esp_wifi_ap_wps_start(const unsigned char *pin)
253275
return ESP_ERR_WIFI_MODE;
254276
}
255277

256-
API_MUTEX_TAKE();
257278

258279
if (!s_wps_enabled) {
259280
wpa_printf(MSG_ERROR, "wps start: wps not enabled");
260281
API_MUTEX_GIVE();
261282
return ESP_ERR_WIFI_WPS_SM;
262283
}
263284

264-
if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
265-
wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d", wps_get_type(), wps_get_status());
266-
API_MUTEX_GIVE();
285+
if (wps_get_type() == WPS_TYPE_DISABLE ||
286+
(wps_get_status() != WPS_STATUS_DISABLE &&
287+
wps_get_status() != WPS_STATUS_SCANNING)) {
288+
wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d",
289+
wps_get_type(), wps_get_status());
267290
return ESP_ERR_WIFI_WPS_TYPE;
268291
}
269292

270293
if (esp_wifi_get_user_init_flag_internal() == 0) {
271-
wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d", esp_wifi_get_user_init_flag_internal());
272-
API_MUTEX_GIVE();
294+
wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d",
295+
esp_wifi_get_user_init_flag_internal());
273296
return ESP_ERR_WIFI_STATE;
274297
}
275298

276299
if (!pin) {
277300
pin = gWpsSm->wps->dev_password;
278301
}
302+
279303
/* TODO ideally SoftAP mode should also do a single scan in PBC mode
280304
* however softAP scanning is not available at the moment */
281-
wps_set_status(WPS_STATUS_PENDING);
305+
if (wps_set_status(WPS_STATUS_PENDING) != ESP_OK) {
306+
return ESP_FAIL;
307+
}
282308
if (wps_get_type() == WPS_TYPE_PBC) {
283-
hostapd_wps_button_pushed(hostapd_get_hapd_data(), NULL);
309+
if (hostapd_wps_button_pushed(hostapd_get_hapd_data(), NULL) != ESP_OK) {
310+
return ESP_FAIL;
311+
}
284312
} else if (wps_get_type() == WPS_TYPE_PIN) {
285-
hostapd_wps_add_pin(hostapd_get_hapd_data(), pin);
313+
if (hostapd_wps_add_pin(hostapd_get_hapd_data(), pin) != ESP_OK) {
314+
return ESP_FAIL;
315+
}
286316
}
287-
API_MUTEX_GIVE();
288317
return ESP_OK;
289318
}
319+
320+
int esp_wifi_ap_wps_start(const unsigned char *pin)
321+
{
322+
int ret = ESP_FAIL;
323+
API_MUTEX_TAKE();
324+
ret = wps_reg_eloop_post_block(SIG_WPS_REG_START, (void *)pin);
325+
API_MUTEX_GIVE();
326+
return ret;
327+
}
328+
329+
static void wps_reg_eloop_handler(void *eloop_ctx, void *user_ctx)
330+
{
331+
int ret = ESP_FAIL;
332+
enum wps_reg_sig_type *sig = (enum wps_reg_sig_type *) eloop_ctx;
333+
wps_ioctl_param_t *param = (wps_ioctl_param_t *) user_ctx;
334+
335+
switch(*sig) {
336+
case SIG_WPS_REG_ENABLE:
337+
esp_wps_config_t *config = (esp_wps_config_t *)param->arg;
338+
ret = wifi_ap_wps_enable_internal(config);
339+
break;
340+
case SIG_WPS_REG_START:
341+
unsigned char *pin = (unsigned char *)param->arg;
342+
ret = wifi_ap_wps_start_internal((const unsigned char *)pin);
343+
break;
344+
case SIG_WPS_REG_DISABLE:
345+
ret = wifi_ap_wps_disable_internal();
346+
break;
347+
default:
348+
wpa_printf(MSG_WARN, "%s(): invalid signal type=%d", __func__, *sig);
349+
ret = ESP_FAIL;
350+
break;
351+
}
352+
353+
param->ret = ret;
354+
os_semphr_give(s_wps_api_sem);
355+
}
356+
357+
static int wps_reg_eloop_post_block(uint32_t sig, void *arg)
358+
{
359+
int ret = ESP_FAIL;
360+
wps_ioctl_param_t param;
361+
param.ret = ESP_FAIL;
362+
param.arg = arg;
363+
364+
if (s_wps_api_sem == NULL) {
365+
s_wps_api_sem = os_semphr_create(1, 0);
366+
if (s_wps_api_sem == NULL) {
367+
wpa_printf(MSG_ERROR, "%s(): failed to create WPA API semaphore", __func__);
368+
return ESP_ERR_NO_MEM;
369+
}
370+
}
371+
372+
eloop_register_timeout(0, 0, wps_reg_eloop_handler, (void *)&sig, (void *)&param);
373+
374+
if (TRUE == os_semphr_take(s_wps_api_sem, OS_BLOCK)) {
375+
ret = param.ret;
376+
} else {
377+
ret = ESP_FAIL;
378+
}
379+
380+
return ret;
381+
}

components/wpa_supplicant/esp_supplicant/src/esp_wps.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -33,8 +33,8 @@
3333

3434
const char *wps_model_number = CONFIG_IDF_TARGET;
3535

36-
void *s_wps_api_lock = NULL; /* Used in WPS public API only, never be freed */
37-
void *s_wps_api_sem = NULL; /* Sync semaphore used between WPS publi API caller task and WPS task */
36+
void *s_wps_api_lock = NULL; /* Used in WPS/WPS-REG public API only, never be freed */
37+
void *s_wps_api_sem = NULL; /* Sync semaphore used between WPS/WPS-REG public API caller task and WPS task, never be freed */
3838
bool s_wps_enabled = false;
3939
#ifdef USE_WPS_TASK
4040
struct wps_rx_param {
@@ -45,11 +45,6 @@ struct wps_rx_param {
4545
};
4646
static STAILQ_HEAD(,wps_rx_param) s_wps_rxq;
4747

48-
typedef struct {
49-
void *arg;
50-
int ret; /* return value */
51-
} wps_ioctl_param_t;
52-
5348
static void *s_wps_task_hdl = NULL;
5449
static void *s_wps_queue = NULL;
5550
static void *s_wps_data_lock = NULL;

components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -27,6 +27,19 @@ enum wps_sig_type {
2727
SIG_WPS_NUM, //10
2828
};
2929
#endif
30+
31+
enum wps_reg_sig_type {
32+
SIG_WPS_REG_ENABLE = 1, //1
33+
SIG_WPS_REG_DISABLE, //2
34+
SIG_WPS_REG_START, //3
35+
SIG_WPS_REG_MAX, //4
36+
};
37+
38+
typedef struct {
39+
void *arg;
40+
int ret; /* return value */
41+
} wps_ioctl_param_t;
42+
3043
#ifdef ESP_SUPPLICANT
3144
enum wps_sm_state{
3245
WAIT_START,

0 commit comments

Comments
 (0)