Files
wlan-ap/feeds/qca-wifi-7/hostapd/patches/r12-hostapd-fix-dangling-pointer-access-in-hwmodes.patch
John Crispin 68cf54d9f7 qca-wifi-7: update to ath12.5.5
Signed-off-by: John Crispin <john@phrozen.org>
2025-02-27 12:45:52 +01:00

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