From: Nijun Gong Date: Tue, 11 Jul 2023 13:21:21 +0000 (+0800) Subject: Update iface->current_mode when fetching new hw_features X-Git-Tag: hostap_2_11~1032 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1085e3bdc6f666647a605caf6ae55e65f7f0d47e;p=thirdparty%2Fhostap.git Update iface->current_mode when fetching new hw_features When a CHANNEL_LIST_CHANGED event is received, memory of iface->hw_features is freed and allocated again with hostapd_get_hw_features(), but iface->current_mode still refer to the original memory address, which is not correct since that memory has been freed. This could happen in cases where the driver provides channel list updates during the lifetime of the started BSS. Fix this by updated iface->current_mode to point to the new array of hw features. Fixes: 0837863fbc62 ("AP: Handle 6 GHz AP state machine with NO_IR flags") Signed-off-by: Jouni Malinen --- diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 5bef2087d..2fcc437d3 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -79,6 +79,9 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) u16 num_modes, flags; struct hostapd_hw_modes *modes; u8 dfs_domain; + enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY; + bool is_6ghz = false; + bool orig_mode_valid = false; if (hostapd_drv_none(hapd)) return -1; @@ -95,6 +98,20 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) iface->hw_flags = flags; iface->dfs_domain = dfs_domain; + if (iface->current_mode) { + /* + * Received driver event CHANNEL_LIST_CHANGED when the current + * hw mode is valid. Clear iface->current_mode temporarily as + * the mode instance will be replaced with a new instance and + * the current pointer would be pointing to freed memory. + */ + orig_mode_valid = true; + mode = iface->current_mode->mode; + is_6ghz = mode == HOSTAPD_MODE_IEEE80211A && + iface->current_mode->num_channels > 0 && + is_6ghz_freq(iface->current_mode->channels[0].freq); + iface->current_mode = NULL; + } hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); iface->hw_features = modes; iface->num_hw_features = num_modes; @@ -104,6 +121,12 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) int dfs_enabled = hapd->iconf->ieee80211h && (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); + /* Restore orignal mode if possible */ + if (orig_mode_valid && feature->mode == mode && + feature->num_channels > 0 && + is_6ghz == is_6ghz_freq(feature->channels[0].freq)) + iface->current_mode = feature; + /* set flag for channels we can use in current regulatory * domain */ for (j = 0; j < feature->num_channels; j++) { @@ -141,6 +164,12 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) } } + if (orig_mode_valid && !iface->current_mode) { + wpa_printf(MSG_ERROR, + "%s: Could not update iface->current_mode", + __func__); + } + return 0; }