Fix hostapd initialization error path on allocation failure
If hostapd_alloc_bss_data() failed to allocate the struct hostapd_data instance, dynamic interface addition path ended up trying to dereference freed memory due to incorrect cleanup steps. Fix this by decrementing the interface count when the newly added interface is removed. In addition, make the setup more robust by clearing all changes within hostapd_data_alloc() if any of the allocations fails. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
d58ade2121
commit
2801659268
1 changed files with 24 additions and 18 deletions
|
@ -1872,33 +1872,37 @@ hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct hostapd_iface * hostapd_data_alloc(
|
static int hostapd_data_alloc(struct hostapd_iface *hapd_iface,
|
||||||
struct hapd_interfaces *interfaces, struct hostapd_config *conf)
|
struct hostapd_config *conf)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
struct hostapd_iface *hapd_iface =
|
|
||||||
interfaces->iface[interfaces->count - 1];
|
|
||||||
struct hostapd_data *hapd;
|
struct hostapd_data *hapd;
|
||||||
|
|
||||||
hapd_iface->conf = conf;
|
|
||||||
hapd_iface->num_bss = conf->num_bss;
|
|
||||||
|
|
||||||
hapd_iface->bss = os_calloc(conf->num_bss,
|
hapd_iface->bss = os_calloc(conf->num_bss,
|
||||||
sizeof(struct hostapd_data *));
|
sizeof(struct hostapd_data *));
|
||||||
if (hapd_iface->bss == NULL)
|
if (hapd_iface->bss == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < conf->num_bss; i++) {
|
for (i = 0; i < conf->num_bss; i++) {
|
||||||
hapd = hapd_iface->bss[i] =
|
hapd = hapd_iface->bss[i] =
|
||||||
hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
|
hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
|
||||||
if (hapd == NULL)
|
if (hapd == NULL) {
|
||||||
return NULL;
|
while (i > 0) {
|
||||||
|
i--;
|
||||||
|
os_free(hapd_iface->bss[i]);
|
||||||
|
hapd_iface->bss[i] = NULL;
|
||||||
|
}
|
||||||
|
os_free(hapd_iface->bss);
|
||||||
|
hapd_iface->bss = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
hapd->msg_ctx = hapd;
|
hapd->msg_ctx = hapd;
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd_iface->interfaces = interfaces;
|
hapd_iface->conf = conf;
|
||||||
|
hapd_iface->num_bss = conf->num_bss;
|
||||||
|
|
||||||
return hapd_iface;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1945,13 +1949,10 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_iface) {
|
if (new_iface) {
|
||||||
if (interfaces->driver_init(hapd_iface)) {
|
if (interfaces->driver_init(hapd_iface))
|
||||||
interfaces->count--;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
if (hostapd_setup_interface(hapd_iface)) {
|
if (hostapd_setup_interface(hapd_iface)) {
|
||||||
interfaces->count--;
|
|
||||||
hostapd_deinit_driver(
|
hostapd_deinit_driver(
|
||||||
hapd_iface->bss[0]->driver,
|
hapd_iface->bss[0]->driver,
|
||||||
hapd_iface->bss[0]->drv_priv,
|
hapd_iface->bss[0]->drv_priv,
|
||||||
|
@ -2005,6 +2006,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
|
||||||
"for interface", __func__);
|
"for interface", __func__);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
new_iface = hapd_iface;
|
||||||
|
|
||||||
if (conf_file && interfaces->config_read_cb) {
|
if (conf_file && interfaces->config_read_cb) {
|
||||||
conf = interfaces->config_read_cb(conf_file);
|
conf = interfaces->config_read_cb(conf_file);
|
||||||
|
@ -2019,8 +2021,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd_iface = hostapd_data_alloc(interfaces, conf);
|
if (hostapd_data_alloc(hapd_iface, conf) < 0) {
|
||||||
if (hapd_iface == NULL) {
|
|
||||||
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
|
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
|
||||||
"for hostapd", __func__);
|
"for hostapd", __func__);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -2056,6 +2057,10 @@ fail:
|
||||||
os_free(hapd_iface->bss);
|
os_free(hapd_iface->bss);
|
||||||
hapd_iface->bss = NULL;
|
hapd_iface->bss = NULL;
|
||||||
}
|
}
|
||||||
|
if (new_iface) {
|
||||||
|
interfaces->count--;
|
||||||
|
interfaces->iface[interfaces->count] = NULL;
|
||||||
|
}
|
||||||
hostapd_cleanup_iface(hapd_iface);
|
hostapd_cleanup_iface(hapd_iface);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2076,6 +2081,7 @@ static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
|
||||||
wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
|
wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
|
||||||
__func__, hapd, hapd->conf->iface);
|
__func__, hapd, hapd->conf->iface);
|
||||||
hostapd_config_free_bss(hapd->conf);
|
hostapd_config_free_bss(hapd->conf);
|
||||||
|
hapd->conf = NULL;
|
||||||
os_free(hapd);
|
os_free(hapd);
|
||||||
|
|
||||||
iface->num_bss--;
|
iface->num_bss--;
|
||||||
|
|
Loading…
Reference in a new issue