The scan response handler indexes into TSF and channel-band TLV arrays using a loop counter derived from the number of BSS entries, but never checks whether the TLV data is large enough. A firmware response with fewer TLV entries than BSS entries leads to reads past the TLV buffer. Add bounds checks that verify each indexed access falls within the TLV data length before dereferencing. Initialize chan_band to NULL and fw_tsf to zero at the start of each iteration so that a short TLV does not leave stale values from the previous BSS entry. Gate the neighbor-discovery branch on chan_band being non-NULL to prevent dereferencing an uninitialized pointer when the bounds check rejects the current entry. Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver") Cc: stable@vger.kernel.org Signed-off-by: Tristan Madani --- drivers/net/wireless/marvell/mwifiex/scan.c | 23 ++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index bdd4b8465863b..4c4bbd4b3b73b 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2208,6 +2208,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, } for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { + chan_band = NULL; + fw_tsf = 0; /* * If the TSF TLV was appended to the scan results, save this * entry's TSF value in the fw_tsf field. It is the firmware's @@ -2215,17 +2217,28 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, * received. */ if (tsf_tlv) - memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], - sizeof(fw_tsf)); + if ((idx + 1) * TSF_DATA_SIZE <= + le16_to_cpu(tsf_tlv->header.len)) + memcpy(&fw_tsf, + &tsf_tlv->tsf_data[idx * + TSF_DATA_SIZE], + sizeof(fw_tsf)); if (chan_band_tlv) { - chan_band = &chan_band_tlv->chan_band_param[idx]; - radio_type = &chan_band->radio_type; + if ((idx + 1) * sizeof(*chan_band) <= + le16_to_cpu(chan_band_tlv->header.len)) { + chan_band = + &chan_band_tlv->chan_band_param[idx]; + radio_type = &chan_band->radio_type; + } else { + chan_band = NULL; + radio_type = NULL; + } } else { radio_type = NULL; } - if (chan_band_tlv && adapter->nd_info) { + if (chan_band && chan_band_tlv && adapter->nd_info) { adapter->nd_info->matches[idx] = kzalloc(sizeof(*pmatch) + sizeof(u32), GFP_ATOMIC); -- 2.47.3