From c00909213c37f36b6f00af08f757e1b917012830 Mon Sep 17 00:00:00 2001 From: Gaofeng Zhang Date: Mon, 13 Jul 2026 16:55:04 +0800 Subject: [PATCH 1/3] [noup] zephyr: fix socket leak when remove supp and hostapd interface When the interface is removed, the hostapd control socket is not closed, resulting in a hostapd control socket leak. Signed-off-by: Gaofeng Zhang --- hostapd/hostapd_cli_zephyr.c | 65 +++++++++++++++++++++++++++++++----- hostapd/hostapd_cli_zephyr.h | 1 + 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/hostapd/hostapd_cli_zephyr.c b/hostapd/hostapd_cli_zephyr.c index 76692703e8..6c8631e61d 100644 --- a/hostapd/hostapd_cli_zephyr.c +++ b/hostapd/hostapd_cli_zephyr.c @@ -268,16 +268,9 @@ static int hostapd_cli_open_connection(struct hostapd_data *hapd) static void hostapd_cli_close_connection(struct hostapd_data *hapd) { - int ret; - if (!hapd || !hapd->iface || hapd->iface->ctrl_conn == NULL) return; - ret = wpa_ctrl_detach(hapd->iface->ctrl_conn); - if (ret < 0) { - wpa_printf(MSG_INFO, "Failed to detach from wpa_supplicant: %s", - strerror(errno)); - } wpa_ctrl_close(hapd->iface->ctrl_conn); hapd->iface->ctrl_conn = NULL; } @@ -336,7 +329,61 @@ int zephyr_hostapd_ctrl_init(void *ctx) return ret; } -void zephyr_hostapd_ctrl_deinit(void *hapd) +/* + * hapd_ctrl_close_fds - eloop callback to close ctrl sockets in eloop thread + * + * eloop_ctx: recv_sock fd encoded as (void *)(intptr_t) + * user_ctx: send_sock fd encoded as (void *)(intptr_t) + * + * Encoding fds as pointer-sized integers avoids any heap allocation, so this + * callback can always be scheduled via eloop_register_timeout regardless of + * memory pressure. + */ +static void hapd_ctrl_close_fds(void *eloop_ctx, void *user_ctx) +{ + int recv_sock = (int)(intptr_t)eloop_ctx; + int send_sock = (int)(intptr_t)user_ctx; + + /* Now in eloop thread, safe to unregister and close */ + if (recv_sock >= 0) { + eloop_unregister_read_sock(recv_sock); + close(recv_sock); + } + if (send_sock >= 0) + close(send_sock); +} + +void zephyr_hostapd_ctrl_deinit(void *hapd_ctx) { - hostapd_cli_close_connection((struct hostapd_data *)hapd); + struct hostapd_data *hapd = (struct hostapd_data *)hapd_ctx; + int recv_sock, send_sock; + + if (!hapd) + return; + + /* Close ctrl_conn (frees wpa_ctrl struct only, no fd close) */ + hostapd_cli_close_connection(hapd); + + recv_sock = hapd->recv_sock; + send_sock = hapd->send_sock; + hapd->recv_sock = -1; + hapd->send_sock = -1; + + /* + * Defer fd close to the eloop thread to avoid racing with + * eloop_unregister_read_sock(). Fds are passed as pointer-sized + * integers so no heap allocation is needed here. + * timeout=0: fires in the next eloop iteration. + */ + if (eloop_register_timeout(0, 0, hapd_ctrl_close_fds, + (void *)(intptr_t)recv_sock, + (void *)(intptr_t)send_sock) < 0) { + /* eloop is shutting down; close inline as last resort */ + if (recv_sock >= 0) { + eloop_unregister_read_sock(recv_sock); + close(recv_sock); + } + if (send_sock >= 0) + close(send_sock); + } } diff --git a/hostapd/hostapd_cli_zephyr.h b/hostapd/hostapd_cli_zephyr.h index 0088fd7152..757a30e7b0 100644 --- a/hostapd/hostapd_cli_zephyr.h +++ b/hostapd/hostapd_cli_zephyr.h @@ -20,5 +20,6 @@ int hostapd_ctrl_command_interactive(struct wpa_ctrl *ctrl, const char *cmd); int zephyr_hostapd_cli_cmd_resp(struct wpa_ctrl *ctrl, const char *cmd, char *resp); int zephyr_hostapd_cli_cmd_v(struct wpa_ctrl *ctrl, const char *fmt, ...); int zephyr_hostapd_ctrl_init(void *ctx); +void zephyr_hostapd_ctrl_deinit(void *hapd); int zephyr_hostapd_ctrl_zephyr_cmd(struct wpa_ctrl *ctrl, int argc, const char *argv[]); #endif /* __HOSTAPD_CLI_ZEPHYR_H_ */ From f884e3893e4fba338c6a15f0fd22c9712a4a499e Mon Sep 17 00:00:00 2001 From: Gaofeng Zhang Date: Mon, 13 Jul 2026 16:55:32 +0800 Subject: [PATCH 2/3] [noup] zephyr: fix memory leak when wifi remove interface When removing the wifi interface, hostapd_deinit() cannot retrieve the zephyr driver dev_ops, which causes the memory allocated during hostapd_init() to not be freed properly, resulting in a memory leak. Signed-off-by: Gaofeng Zhang --- src/drivers/driver_zephyr.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index a2dc1f4cad..7f372eaf42 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1491,16 +1491,27 @@ static void wpa_drv_zep_hapd_deinit(void *priv) struct zep_drv_if_ctx *if_ctx = NULL; const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + if (!priv) { + wpa_printf(MSG_ERROR, "%s: Invalid params", __func__); + return; + } + if_ctx = priv; - dev_ops = (struct zep_wpa_supp_dev_ops *)if_ctx->dev_ops; - if (!dev_ops->hapd_deinit) { + if (!if_ctx->dev_ctx) { + wpa_printf(MSG_ERROR, "%s: dev_ctx is NULL", __func__); + goto out; + } + + dev_ops = get_dev_ops(if_ctx->dev_ctx); + if (!dev_ops || !dev_ops->hapd_deinit) { wpa_printf(MSG_ERROR, "%s: No op registered for hapd deinit", __func__); - return; + goto out; } dev_ops->hapd_deinit(if_ctx->dev_priv); +out: os_free(if_ctx); } From eb41ef013ac592222447a58bc85060e3503efb87 Mon Sep 17 00:00:00 2001 From: Gaofeng Zhang Date: Thu, 16 Jul 2026 15:59:29 +0800 Subject: [PATCH 3/3] [noup] zephyr: fix hang issue when remove supp and hostapd interface when hostapd and supplicant interface is removed, zep_drv_if_ctx is free in hostapd and supplicant driver deinit. so need to check zep_drv_if_ctx if function parameteris zep_drv_if_ctx Signed-off-by: Gaofeng Zhang --- src/drivers/driver_zephyr.c | 125 ++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 7f372eaf42..3973d40730 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -385,6 +385,12 @@ void wpa_supplicant_event_wrapper(void *ctx, void wpa_drv_zep_event_chan_list_changed(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + #ifdef CONFIG_WIFI_NM_HOSTAPD_AP if (if_ctx->hapd) hostapd_event_wrapper(if_ctx->hapd, EVENT_CHANNEL_LIST_CHANGED, event); @@ -397,6 +403,10 @@ void wpa_drv_zep_event_chan_list_changed(struct zep_drv_if_ctx *if_ctx, union wp void wpa_drv_zep_event_mac_changed(struct zep_drv_if_ctx *if_ctx) { + if (!if_ctx) { + wpa_printf(MSG_WARNING, "%s: Missing interface context", __func__); + return; + } #ifdef CONFIG_WIFI_NM_HOSTAPD_AP const struct net_linkaddr *link_addr = NULL; @@ -458,6 +468,12 @@ void wpa_drv_zep_scan_timeout(void *eloop_ctx, void *timeout_ctx) void wpa_drv_zep_event_proc_scan_start(struct zep_drv_if_ctx *if_ctx) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_SCAN_STARTED, NULL); @@ -467,6 +483,12 @@ void wpa_drv_zep_event_proc_scan_start(struct zep_drv_if_ctx *if_ctx) void wpa_drv_zep_event_proc_scan_done(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + eloop_cancel_timeout(wpa_drv_zep_scan_timeout, if_ctx, if_ctx->supp_if_ctx); @@ -487,6 +509,12 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, struct wpa_scan_res **tmp = NULL; size_t scan_res_len = sizeof(struct wpa_scan_res) + r->ie_len + r->beacon_ie_len; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + if (!if_ctx->scan_res2) return; @@ -527,6 +555,12 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, */ void wpa_drv_zep_event_proc_sched_scan_stopped(struct zep_drv_if_ctx *if_ctx) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_SCHED_SCAN_STOPPED, NULL); @@ -535,6 +569,13 @@ void wpa_drv_zep_event_proc_sched_scan_stopped(struct zep_drv_if_ctx *if_ctx) void wpa_drv_zep_event_proc_auth_resp(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_AUTH, event); @@ -545,6 +586,12 @@ void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event, unsigned int status) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + if (status != WLAN_STATUS_SUCCESS) { if (if_ctx->ft_roaming) { if_ctx->ft_roaming = false; @@ -574,6 +621,12 @@ void wpa_drv_zep_event_proc_deauth(struct zep_drv_if_ctx *if_ctx, { const u8 *bssid = NULL; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + bssid = mgmt->bssid; if ((if_ctx->capa.flags & WPA_DRIVER_FLAGS_SME) && @@ -605,6 +658,12 @@ void wpa_drv_zep_event_proc_deauth(struct zep_drv_if_ctx *if_ctx, void wpa_drv_zep_event_proc_disassoc(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_DISASSOC, event); @@ -653,6 +712,12 @@ static void wpa_drv_zep_event_mgmt_tx_status(struct zep_drv_if_ctx *if_ctx, const struct ieee80211_hdr *hdr; u16 fc; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_printf(MSG_DEBUG, "wpa_supp: Frame TX status event"); hdr = (const struct ieee80211_hdr *) frame; @@ -690,6 +755,11 @@ static void wpa_drv_zep_event_mgmt_tx_status(struct zep_drv_if_ctx *if_ctx, static void wpa_drv_zep_event_proc_unprot_deauth(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_UNPROT_DEAUTH, event); @@ -698,6 +768,11 @@ static void wpa_drv_zep_event_proc_unprot_deauth(struct zep_drv_if_ctx *if_ctx, static void wpa_drv_zep_event_proc_unprot_disassoc(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_UNPROT_DISASSOC, event); @@ -940,6 +1015,11 @@ static int phy_info_band_cfg(struct phy_info_arg *phy_info, static void wpa_drv_zep_event_get_wiphy(struct zep_drv_if_ctx *if_ctx, void *band_info) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } if (!band_info) { /* Done with all bands */ k_sem_give(&if_ctx->drv_resp_sem); @@ -1019,6 +1099,12 @@ static void wpa_drv_zep_event_mgmt_rx(struct zep_drv_if_ctx *if_ctx, u16 fc, stype; int rx_freq = 0; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + wpa_printf(MSG_MSGDUMP, "wpa_supp: Frame event"); mgmt = (const struct ieee80211_mgmt *)frame; @@ -1055,6 +1141,10 @@ static void wpa_drv_zep_event_mgmt_rx(struct zep_drv_if_ctx *if_ctx, static void wpa_drv_zep_event_ecsa_complete(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf(MSG_WARNING, "%s: Missing interface context", __func__); + return; + } #ifdef CONFIG_WIFI_NM_HOSTAPD_AP if (if_ctx->hapd) hostapd_event_wrapper(if_ctx->hapd, EVENT_CH_SWITCH, event); @@ -1066,6 +1156,10 @@ static void wpa_drv_zep_event_ecsa_complete(struct zep_drv_if_ctx *if_ctx, union #ifdef CONFIG_WIFI_NM_HOSTAPD_AP static void wpa_drv_zep_event_dfs_cac_started(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf(MSG_WARNING, "%s: if_ctx is not inited", __func__); + return; + } if (if_ctx->hapd) hostapd_event_wrapper(if_ctx->hapd, EVENT_DFS_CAC_STARTED, event); else @@ -1074,6 +1168,10 @@ static void wpa_drv_zep_event_dfs_cac_started(struct zep_drv_if_ctx *if_ctx, uni static void wpa_drv_zep_event_dfs_cac_finished(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf(MSG_WARNING, "%s: if_ctx is not inited", __func__); + return; + } if (if_ctx->hapd) hostapd_event_wrapper(if_ctx->hapd, EVENT_DFS_CAC_FINISHED, event); else @@ -1084,6 +1182,11 @@ static void wpa_drv_zep_event_dfs_cac_finished(struct zep_drv_if_ctx *if_ctx, un static void wpa_drv_zep_event_signal_change(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_SIGNAL_CHANGE, event); } @@ -1092,6 +1195,12 @@ static void wpa_drv_zep_event_roc_complete(struct zep_drv_if_ctx *if_ctx, { union wpa_event_data event; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + if (cookie != if_ctx->remain_on_channel_cookie) { wpa_printf(MSG_DEBUG, "wpa_supp: No matching cookie found for ROC complete event"); return; @@ -1109,6 +1218,12 @@ static void wpa_drv_zep_event_roc_cancel_complete(struct zep_drv_if_ctx *if_ctx, { union wpa_event_data event; + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } + if (cookie == if_ctx->remain_on_channel_cookie) { os_memset(&event, 0, sizeof(event)); event.remain_on_channel.freq = freq; @@ -1120,6 +1235,11 @@ static void wpa_drv_zep_event_roc_cancel_complete(struct zep_drv_if_ctx *if_ctx, static void wpa_drv_zep_event_cookie_event(struct zep_drv_if_ctx *if_ctx, u64 host_cookie, u64 cookie) { + if (!if_ctx) { + wpa_printf( + MSG_WARNING, "%s: Missing interface context", __func__); + return; + } if (if_ctx->pending_remain_on_channel) { if_ctx->remain_on_channel_cookie = cookie; if_ctx->pending_remain_on_channel = false; @@ -1413,6 +1533,11 @@ static void wpa_drv_zep_deinit(void *priv) #ifdef CONFIG_WIFI_NM_HOSTAPD_AP static void wpa_drv_zep_event_acs_channel_selected(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { + if (!if_ctx) { + wpa_printf(MSG_WARNING, "%s: if_ctx is not inited", __func__); + return; + } + if (if_ctx->hapd) hostapd_event_wrapper(if_ctx->hapd, EVENT_ACS_CHANNEL_SELECTED, event); else