Flush pending control interface message for an interface to be removed
wpa_supplicant_ctrl_iface_deinit() was executed only if the per-interface control interface initialization had been completed. This is not the case if driver initialization fails and that could result in leaving behind references to the freed wpa_s instance in a corner case where control interface messages ended up getting queued. Fix this by calling wpa_supplicant_ctrl_iface_deinit() in all cases to cancel the potential eloop timeout for wpas_ctrl_msg_queue_timeout with the reference to the wpa_s pointer. In addition, flush any pending message from the global queue for this interface since such a message cannot be of use after this and there is no need to leave them in the queue until the global control interface gets deinitialized. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
6bcd4abdc1
commit
8ca330bd70
7 changed files with 66 additions and 20 deletions
|
@ -70,14 +70,17 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
|
|||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
|
||||
*
|
||||
* Deinitialize the control interface that was initialized with
|
||||
* wpa_supplicant_ctrl_iface_init().
|
||||
* wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
|
||||
* @priv may be %NULL if the control interface has not yet been initialized.
|
||||
*
|
||||
* Required to be implemented in each control interface backend.
|
||||
*/
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv);
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
|
||||
|
@ -128,7 +131,8 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
static inline void
|
||||
wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
||||
wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -462,8 +462,11 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
if (!priv)
|
||||
return;
|
||||
while (priv->ctrl_dst)
|
||||
ctrl_close_pipe(priv->ctrl_dst);
|
||||
if (priv->sec_attr_set)
|
||||
|
|
|
@ -490,8 +490,12 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
if (priv->sock > -1) {
|
||||
eloop_unregister_read_sock(priv->sock);
|
||||
if (priv->ctrl_dst) {
|
||||
|
|
|
@ -800,12 +800,52 @@ static int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
||||
static void
|
||||
wpas_global_ctrl_iface_flush_queued_msg(struct wpa_global *global,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct ctrl_iface_global_priv *gpriv;
|
||||
struct ctrl_iface_msg *msg, *prev_msg;
|
||||
unsigned int count = 0;
|
||||
|
||||
if (!global || !global->ctrl_iface)
|
||||
return;
|
||||
|
||||
gpriv = global->ctrl_iface;
|
||||
dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
|
||||
struct ctrl_iface_msg, list) {
|
||||
if (msg->wpa_s == wpa_s) {
|
||||
count++;
|
||||
dl_list_del(&msg->list);
|
||||
os_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (count) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"CTRL: Dropped %u pending message(s) for interface that is being removed",
|
||||
count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||
struct ctrl_iface_priv *priv)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst, *prev;
|
||||
struct ctrl_iface_msg *msg, *prev_msg;
|
||||
struct ctrl_iface_global_priv *gpriv;
|
||||
|
||||
if (!priv) {
|
||||
/* Control interface has not yet been initialized, so there is
|
||||
* nothing to deinitialize here. However, there might be a
|
||||
* pending message for this interface, so get rid of any such
|
||||
* entry before completing interface removal. */
|
||||
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
|
||||
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->sock > -1) {
|
||||
char *fname;
|
||||
char *buf, *dir = NULL;
|
||||
|
@ -877,6 +917,7 @@ free_dst:
|
|||
}
|
||||
}
|
||||
}
|
||||
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
|
||||
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
|
||||
os_free(priv);
|
||||
}
|
||||
|
|
|
@ -674,10 +674,8 @@ static void test_eapol_clean(struct eapol_test_data *e,
|
|||
os_free(e->radius_conf);
|
||||
e->radius_conf = NULL;
|
||||
scard_deinit(wpa_s->scard);
|
||||
if (wpa_s->ctrl_iface) {
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
}
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
|
||||
ext_password_deinit(wpa_s->ext_pw);
|
||||
wpa_s->ext_pw = NULL;
|
||||
|
|
|
@ -193,10 +193,8 @@ static void test_eapol_clean(struct wpa_supplicant *wpa_s)
|
|||
pmksa_candidate_free(wpa_s->wpa);
|
||||
wpa_sm_deinit(wpa_s->wpa);
|
||||
scard_deinit(wpa_s->scard);
|
||||
if (wpa_s->ctrl_iface) {
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
}
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
wpa_config_free(wpa_s->conf);
|
||||
}
|
||||
|
||||
|
|
|
@ -1158,8 +1158,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
|
|||
os_strcmp(conf->ctrl_interface,
|
||||
wpa_s->conf->ctrl_interface) != 0);
|
||||
|
||||
if (reconf_ctrl && wpa_s->ctrl_iface) {
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
||||
if (reconf_ctrl) {
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
}
|
||||
|
||||
|
@ -6748,10 +6748,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
|
|||
if (terminate)
|
||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
|
||||
|
||||
if (wpa_s->ctrl_iface) {
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
}
|
||||
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||
wpa_s->ctrl_iface = NULL;
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
if (wpa_s->ifmsh) {
|
||||
|
|
Loading…
Reference in a new issue