mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-30 01:52:51 +00:00
160 lines
4.6 KiB
Diff
160 lines
4.6 KiB
Diff
From 5c826cda720bf19d6ca6557a0076907193d94454 Mon Sep 17 00:00:00 2001
|
|
From: Govindaraj Saminathan <quic_gsaminat@quicinc.com>
|
|
Date: Wed, 17 Jan 2024 10:20:15 +0530
|
|
Subject: [PATCH] hostapd: fix dangling pointer access during channel list update
|
|
|
|
Whenever the channel list change event received along with reg domain
|
|
set initiate by driver, Memory reallocated for new hw modes to update
|
|
the no_ir channel list, but the iface current_mode pointer still
|
|
referring with old memory which cause for dangling pointer access and crash.
|
|
|
|
Moving to local pointers to update the no_ir channel list and later
|
|
regdomain changes are properly updated using setup interface subroutine.
|
|
|
|
Signed-off-by: Govindaraj Saminathan <quic_gsaminat@quicinc.com>
|
|
---
|
|
src/ap/hostapd.c | 64 +++++++++++++++++++++++++++++-------------------
|
|
1 file changed, 39 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
|
|
index 8d0be71392e3..b636e5c0ba3b 100644
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -1895,59 +1895,71 @@ static void hostapd_no_ir_cleanup(struct hostapd_data *bss)
|
|
static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
|
|
void *ctx)
|
|
{
|
|
+ struct hostapd_data *hapd = iface->bss[0];
|
|
bool all_no_ir, is_6ghz;
|
|
int i, j;
|
|
- struct hostapd_hw_modes *mode = NULL;
|
|
+ struct hostapd_hw_modes *hw_mode = NULL, *hw_features;
|
|
+ u16 num_hw_features, flags;
|
|
+ u8 dfs_domain;
|
|
|
|
- if (hostapd_get_hw_features(iface))
|
|
- return 0;
|
|
+ if (hostapd_drv_none(hapd))
|
|
+ return -1;
|
|
+
|
|
+ hw_features = hostapd_get_hw_feature_data(hapd, &num_hw_features, &flags,
|
|
+ &dfs_domain);
|
|
+ if (hw_features == NULL) {
|
|
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
|
+ HOSTAPD_LEVEL_DEBUG,
|
|
+ "Fetching hardware channel/rate support not "
|
|
+ "supported.");
|
|
+ return -1;
|
|
+ }
|
|
|
|
all_no_ir = true;
|
|
is_6ghz = false;
|
|
|
|
- for (i = 0; i < iface->num_hw_features; i++) {
|
|
- mode = &iface->hw_features[i];
|
|
+ for (i = 0; i < num_hw_features; i++) {
|
|
+ hw_mode = &hw_features[i];
|
|
|
|
- if (mode->mode == iface->conf->hw_mode) {
|
|
+ if (hw_mode->mode == iface->conf->hw_mode) {
|
|
if (iface->freq > 0 &&
|
|
- !hw_mode_get_channel(mode, iface->freq, NULL)) {
|
|
- mode = NULL;
|
|
+ !hw_mode_get_channel(hw_mode, iface->freq, NULL)) {
|
|
+ hw_mode = NULL;
|
|
continue;
|
|
}
|
|
|
|
- for (j = 0; j < mode->num_channels; j++) {
|
|
- if (!(mode->channels[j].flag &
|
|
+ for (j = 0; j < hw_mode->num_channels; j++) {
|
|
+ if (!(hw_mode->channels[j].flag &
|
|
HOSTAPD_CHAN_NO_IR))
|
|
all_no_ir = false;
|
|
|
|
- if (is_6ghz_freq(mode->channels[j].freq))
|
|
+ if (is_6ghz_freq(hw_mode->channels[j].freq))
|
|
is_6ghz = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
- if (!mode || !is_6ghz)
|
|
- return 0;
|
|
- iface->current_mode = mode;
|
|
+ if (!hw_mode || !is_6ghz)
|
|
+ goto free_hw_features;
|
|
|
|
if (iface->state == HAPD_IFACE_ENABLED) {
|
|
if (!all_no_ir) {
|
|
struct hostapd_channel_data *chan;
|
|
|
|
- chan = hw_get_channel_freq(iface->current_mode->mode,
|
|
+ chan = hw_get_channel_freq(hw_mode->mode,
|
|
iface->freq, NULL,
|
|
- iface->hw_features,
|
|
- iface->num_hw_features);
|
|
+ hw_features,
|
|
+ num_hw_features);
|
|
|
|
if (!chan) {
|
|
wpa_printf(MSG_ERROR,
|
|
"NO_IR: Could not derive chan from freq");
|
|
- return 0;
|
|
+ goto free_hw_features;
|
|
}
|
|
|
|
if (!(chan->flag & HOSTAPD_CHAN_NO_IR))
|
|
- return 0;
|
|
+ goto free_hw_features;
|
|
wpa_printf(MSG_DEBUG,
|
|
"NO_IR: The current channel has NO_IR flag now, stop AP.");
|
|
} else {
|
|
@@ -1964,20 +1976,20 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
|
|
if (all_no_ir) {
|
|
wpa_printf(MSG_DEBUG,
|
|
"NO_IR: AP in NO_IR and all chan in the new chanlist are NO_IR. Ignore");
|
|
- return 0;
|
|
+ goto free_hw_features;
|
|
}
|
|
|
|
if (!iface->conf->acs) {
|
|
struct hostapd_channel_data *chan;
|
|
|
|
- chan = hw_get_channel_freq(iface->current_mode->mode,
|
|
+ chan = hw_get_channel_freq(hw_mode->mode,
|
|
iface->freq, NULL,
|
|
- iface->hw_features,
|
|
- iface->num_hw_features);
|
|
+ hw_features,
|
|
+ num_hw_features);
|
|
if (!chan) {
|
|
wpa_printf(MSG_ERROR,
|
|
"NO_IR: Could not derive chan from freq");
|
|
- return 0;
|
|
+ goto free_hw_features;
|
|
}
|
|
|
|
/* If the last operating channel is NO_IR, trigger ACS.
|
|
@@ -1988,13 +2000,15 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
|
|
if (acs_init(iface) != HOSTAPD_CHAN_ACS)
|
|
wpa_printf(MSG_ERROR,
|
|
"NO_IR: Could not start ACS");
|
|
- return 0;
|
|
+ goto free_hw_features;
|
|
}
|
|
}
|
|
|
|
setup_interface2(iface);
|
|
}
|
|
|
|
+free_hw_features:
|
|
+ hostapd_free_hw_features(hw_features, num_hw_features);
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
2.17.1
|
|
|