]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Handle garbage pointer after MLD interface is deleted
authorNaveen S <quic_naves@quicinc.com>
Thu, 25 Apr 2024 10:15:23 +0000 (15:45 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 9 Aug 2024 06:56:22 +0000 (09:56 +0300)
In function driver_nl80211_link_remove(), when there is no active links,
interface is removed. This will free the BSS pointer. A copy of the BSS
pointer is also stored in each of the affiliated links' hapd->drv_priv
member.

driver_nl80211_link_remove() is called via multiple paths, e.g., via
NL80211_CMD_STOP_AP and via driver_nl80211_ops. When called when
handling an nl80211 event, links will be removed and when count reaches
zero, the interface will be removed. However, core hostapd will be
unaware of this removal. Hence, if it tries to access its drv_priv
pointer, this can lead to segmentation fault at times since the pointer
is now pointing to freed memory.

Prevent this by adding a new notification event
(EVENT_MLD_INTERFACE_FREED). Whenever the interface is freed, this
notification will be sent. hostapd will process this notification and
will set all affliated links' hapd->drv_priv to NULL.

Signed-off-by: Naveen S <quic_naves@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/ap/hostapd.h
src/drivers/driver.h
src/drivers/driver_common.c
src/drivers/driver_nl80211.c

index 9e9b46bb1ea6616dff4f53e2f1e3c38511456b57..6c98cb903ba41400d4c4ab8df5b753ae5912a54a 100644 (file)
@@ -2859,6 +2859,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                hostapd_event_color_change(hapd, true);
                break;
 #endif /* CONFIG_IEEE80211AX */
+#ifdef CONFIG_IEEE80211BE
+       case EVENT_MLD_INTERFACE_FREED:
+               wpa_printf(MSG_DEBUG, "MLD: Interface %s freed",
+                          hapd->conf->iface);
+               hostapd_mld_interface_freed(hapd);
+               break;
+#endif /* CONFIG_IEEE80211BE */
        default:
                wpa_printf(MSG_DEBUG, "Unknown event %d", event);
                break;
index 146b4960f409f82a90e9c61e7b741cb9c7dbbac7..0c3f1d7092f0a6cdddde3bf5b4823ea662a8c565 100644 (file)
@@ -3402,6 +3402,7 @@ static void hostapd_cleanup_driver(const struct wpa_driver_ops *driver,
                   driver->is_drv_shared &&
                   !driver->is_drv_shared(drv_priv, iface->bss[0])) {
                driver->hapd_deinit(drv_priv);
+               hostapd_mld_interface_freed(iface->bss[0]);
        } else if (hostapd_if_link_remove(iface->bss[0],
                                          WPA_IF_AP_BSS,
                                          iface->bss[0]->conf->iface,
@@ -4981,6 +4982,18 @@ struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd)
        return mld->fbss;
 }
 
+
+void hostapd_mld_interface_freed(struct hostapd_data *hapd)
+{
+       struct hostapd_data *link_bss = NULL;
+
+       if (!hapd || !hapd->conf->mld_ap)
+               return;
+
+       for_each_mld_link(link_bss, hapd)
+               link_bss->drv_priv = NULL;
+}
+
 #endif /* CONFIG_IEEE80211BE */
 
 
index 0df67038314dda7793e02fba51ae14a399411b0d..278e9c3cad0d781bc4df9ad6c68368c585954197 100644 (file)
@@ -852,6 +852,7 @@ int hostapd_fill_cca_settings(struct hostapd_data *hapd,
 #ifdef CONFIG_IEEE80211BE
 
 bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
+void hostapd_mld_interface_freed(struct hostapd_data *hapd);
 
 #define for_each_mld_link(partner, self) \
        dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
index 4331782d897adeb11f6842a503cbb8d1935ef1bf..616f011a89d4c234686924a12afe3bc141bc24c0 100644 (file)
@@ -5847,6 +5847,11 @@ enum wpa_event_type {
         * EVENT_LINK_RECONFIG - Notification that AP links removed
         */
        EVENT_LINK_RECONFIG,
+
+       /**
+        * EVENT_MLD_INTERFACE_FREED - Notification of AP MLD interface removal
+        */
+       EVENT_MLD_INTERFACE_FREED,
 };
 
 
index 9bc5a731dd82cf006a6b1d0a5c163b4ea70e69ac..9589183d0bd5ab188fa5a7c2007bddc5590deda7 100644 (file)
@@ -100,6 +100,7 @@ const char * event_to_string(enum wpa_event_type event)
        E2S(LINK_CH_SWITCH_STARTED);
        E2S(TID_LINK_MAP);
        E2S(LINK_RECONFIG);
+       E2S(MLD_INTERFACE_FREED);
        }
 
        return "UNKNOWN";
index 5b40737cc18d401b230e2987f7c44ef1d3ee9936..5e0ee0022718522ec56c62cb22f2485c9c11e358 100644 (file)
@@ -10765,6 +10765,7 @@ static int driver_nl80211_link_remove(void *priv, enum wpa_driver_if_type type,
 {
        struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
+       int ret;
 
        if (type != WPA_IF_AP_BSS ||
            !nl80211_link_valid(bss->valid_links, link_id))
@@ -10784,7 +10785,12 @@ static int driver_nl80211_link_remove(void *priv, enum wpa_driver_if_type type,
        if (!bss->valid_links) {
                wpa_printf(MSG_DEBUG,
                           "nl80211: No more links remaining, so remove interface");
-               return wpa_driver_nl80211_if_remove(bss, type, ifname);
+               ret = wpa_driver_nl80211_if_remove(bss, type, ifname);
+               if (ret)
+                       return ret;
+
+               /* Notify that the MLD interface is removed */
+               wpa_supplicant_event(bss->ctx, EVENT_MLD_INTERFACE_FREED, NULL);
        }
 
        return 0;