[PATCH] nl80211: Fix use-after-free during wiphy event handling
Gwen Weinholt
gwen at weinholt.net
Fri Apr 18 04:55:00 PDT 2025
When processing a NL80211_CMD_RADAR_DETECT event, the current driver
interface instance may be deinitialized during the event handler.
The event loop still holds a pointer to the old driver interface,
but using it after deinit can cause a crash.
A previous attempt to fix this relied on checking whether the
interface pointer still appeared in the list of interfaces.
However, that approach is incomplete: if malloc() returns the same
pointer for a newly added interface (as observed occasionally on
glibc 2.31), the check incorrectly assumes the original instance
still exists.
To fix this reliably, this commit introduces a unique instance ID
in the wpa_driver_nl80211_data struct and uses that ID to check
whether the original driver instance is still present in the list.
Fixes: f13683720239 ("nl80211: Pass wiphy events to all affected interfaces")
Signed-off-by: Gwen Weinholt <gwen at weinholt.net>
---
src/drivers/driver_nl80211.c | 2 ++
src/drivers/driver_nl80211.h | 1 +
src/drivers/driver_nl80211_event.c | 8 +++++---
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2cff5bba0..2ed20b915 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2302,6 +2302,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
const char *driver_params,
enum wpa_p2p_mode p2p_mode)
{
+ static unsigned int next_unique_drv_id = 0;
struct wpa_driver_nl80211_data *drv;
struct i802_bss *bss;
char path[128], buf[200], *pos;
@@ -2334,6 +2335,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
drv->ctx = ctx;
drv->hostapd = !!hostapd;
drv->eapol_sock = -1;
+ drv->unique_drv_id = next_unique_drv_id++;
/*
* There is no driver capability flag for this, so assume it is
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index a6f92ff1e..bea87afeb 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -129,6 +129,7 @@ struct wpa_driver_nl80211_data {
u16 mld_capa_and_ops;
} iface_capa[NL80211_IFTYPE_MAX];
unsigned int num_iface_capa;
+ unsigned int unique_drv_id;
int has_capability;
int has_driver_key_mgmt;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 8928b6e04..e7b67371a 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -4256,13 +4256,13 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
static bool nl80211_drv_in_list(struct nl80211_global *global,
- struct wpa_driver_nl80211_data *drv)
+ unsigned int unique_drv_id)
{
struct wpa_driver_nl80211_data *tmp;
dl_list_for_each(tmp, &global->interfaces,
struct wpa_driver_nl80211_data, list) {
- if (drv == tmp)
+ if (tmp->unique_drv_id == unique_drv_id)
return true;
}
@@ -4322,6 +4322,8 @@ int process_global_event(struct nl_msg *msg, void *arg)
dl_list_for_each_safe(drv, tmp, &global->interfaces,
struct wpa_driver_nl80211_data, list) {
+ unsigned int unique_drv_id = drv->unique_drv_id;
+
for (bss = drv->first_bss; bss; bss = bss->next) {
if (wiphy_idx_set)
wiphy_idx = nl80211_get_wiphy_index(bss);
@@ -4347,7 +4349,7 @@ int process_global_event(struct nl_msg *msg, void *arg)
* e.g., due to NL80211_CMD_RADAR_DETECT event,
* so need to stop the loop if that has
* happened. */
- if (!nl80211_drv_in_list(global, drv))
+ if (!nl80211_drv_in_list(global, unique_drv_id))
break;
}
}
--
2.47.2
More information about the Hostap
mailing list