Commit 1afe4a64 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'wireless-2024-06-14' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Johannes Berg says:

====================
Various fixes:
 * cfg80211: wext scan
 * mac80211: monitor regression, scan counted_by, offload
 * iwlwifi: locking, 6 GHz scan, remain-on-channel

* tag 'wireless-2024-06-14' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
  wifi: mac80211: fix monitor channel with chanctx emulation
  wifi: mac80211: Avoid address calculations via out of bounds array indexing
  wifi: mac80211: Recalc offload when monitor stop
  wifi: iwlwifi: scan: correctly check if PSC listen period is needed
  wifi: iwlwifi: mvm: fix ROC version check
  wifi: iwlwifi: mvm: unlock mvm mutex
  wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
  wifi: cfg80211: wext: set ssids=NULL for passive scans
====================

Link: https://lore.kernel.org/r/20240614085710.24103-3-johannes@sipsolutions.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 89aa3619 0d9c2bee
...@@ -4795,7 +4795,7 @@ static int iwl_mvm_roc_station(struct iwl_mvm *mvm, ...@@ -4795,7 +4795,7 @@ static int iwl_mvm_roc_station(struct iwl_mvm *mvm,
if (fw_ver == IWL_FW_CMD_VER_UNKNOWN) { if (fw_ver == IWL_FW_CMD_VER_UNKNOWN) {
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, vif, duration); ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, vif, duration);
} else if (fw_ver == 3) { } else if (fw_ver >= 3) {
ret = iwl_mvm_roc_add_cmd(mvm, channel, vif, duration, ret = iwl_mvm_roc_add_cmd(mvm, channel, vif, duration,
ROC_ACTIVITY_HOTSPOT); ROC_ACTIVITY_HOTSPOT);
} else { } else {
......
...@@ -1830,7 +1830,7 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, ...@@ -1830,7 +1830,7 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
*/ */
if (!iwl_mvm_is_scan_fragmented(params->type)) { if (!iwl_mvm_is_scan_fragmented(params->type)) {
if (!cfg80211_channel_is_psc(params->channels[i]) || if (!cfg80211_channel_is_psc(params->channels[i]) ||
flags & IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN) { psc_no_listen) {
if (unsolicited_probe_on_chan) { if (unsolicited_probe_on_chan) {
max_s_ssids = 2; max_s_ssids = 2;
max_bssids = 6; max_bssids = 6;
......
...@@ -1238,6 +1238,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1238,6 +1238,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (te_data->id >= SESSION_PROTECT_CONF_MAX_ID) { if (te_data->id >= SESSION_PROTECT_CONF_MAX_ID) {
IWL_DEBUG_TE(mvm, IWL_DEBUG_TE(mvm,
"No remain on channel event\n"); "No remain on channel event\n");
mutex_unlock(&mvm->mutex);
return; return;
} }
...@@ -1253,6 +1254,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1253,6 +1254,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
te_data = iwl_mvm_get_roc_te(mvm); te_data = iwl_mvm_get_roc_te(mvm);
if (!te_data) { if (!te_data) {
IWL_WARN(mvm, "No remain on channel event\n"); IWL_WARN(mvm, "No remain on channel event\n");
mutex_unlock(&mvm->mutex);
return; return;
} }
......
...@@ -311,6 +311,18 @@ int drv_assign_vif_chanctx(struct ieee80211_local *local, ...@@ -311,6 +311,18 @@ int drv_assign_vif_chanctx(struct ieee80211_local *local,
might_sleep(); might_sleep();
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
/*
* We should perhaps push emulate chanctx down and only
* make it call ->config() when the chanctx is actually
* assigned here (and unassigned below), but that's yet
* another change to all drivers to add assign/unassign
* emulation callbacks. Maybe later.
*/
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
local->emulate_chanctx &&
!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return 0;
if (!check_sdata_in_driver(sdata)) if (!check_sdata_in_driver(sdata))
return -EIO; return -EIO;
...@@ -338,6 +350,11 @@ void drv_unassign_vif_chanctx(struct ieee80211_local *local, ...@@ -338,6 +350,11 @@ void drv_unassign_vif_chanctx(struct ieee80211_local *local,
might_sleep(); might_sleep();
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
local->emulate_chanctx &&
!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return;
if (!check_sdata_in_driver(sdata)) if (!check_sdata_in_driver(sdata))
return; return;
......
...@@ -686,6 +686,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do ...@@ -686,6 +686,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
ieee80211_del_virtual_monitor(local); ieee80211_del_virtual_monitor(local);
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
ieee80211_recalc_offload(local);
if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
break; break;
...@@ -1121,9 +1122,6 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) ...@@ -1121,9 +1122,6 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
int ret; int ret;
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return 0;
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
...@@ -1145,11 +1143,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) ...@@ -1145,11 +1143,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
ieee80211_set_default_queues(sdata); ieee80211_set_default_queues(sdata);
ret = drv_add_interface(local, sdata); if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
if (WARN_ON(ret)) { ret = drv_add_interface(local, sdata);
/* ok .. stupid driver, it asked for this! */ if (WARN_ON(ret)) {
kfree(sdata); /* ok .. stupid driver, it asked for this! */
return ret; kfree(sdata);
return ret;
}
} }
set_bit(SDATA_STATE_RUNNING, &sdata->state); set_bit(SDATA_STATE_RUNNING, &sdata->state);
...@@ -1187,9 +1187,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) ...@@ -1187,9 +1187,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return;
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
...@@ -1209,7 +1206,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) ...@@ -1209,7 +1206,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
ieee80211_link_release_channel(&sdata->deflink); ieee80211_link_release_channel(&sdata->deflink);
drv_remove_interface(local, sdata); if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
drv_remove_interface(local, sdata);
kfree(sdata); kfree(sdata);
} }
......
...@@ -358,7 +358,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata) ...@@ -358,7 +358,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata)
struct cfg80211_scan_request *req; struct cfg80211_scan_request *req;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
u8 bands_used = 0; u8 bands_used = 0;
int i, ielen, n_chans; int i, ielen;
u32 *n_chans;
u32 flags = 0; u32 flags = 0;
req = rcu_dereference_protected(local->scan_req, req = rcu_dereference_protected(local->scan_req,
...@@ -368,34 +369,34 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata) ...@@ -368,34 +369,34 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata)
return false; return false;
if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) { if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
local->hw_scan_req->req.n_channels = req->n_channels;
for (i = 0; i < req->n_channels; i++) { for (i = 0; i < req->n_channels; i++) {
local->hw_scan_req->req.channels[i] = req->channels[i]; local->hw_scan_req->req.channels[i] = req->channels[i];
bands_used |= BIT(req->channels[i]->band); bands_used |= BIT(req->channels[i]->band);
} }
n_chans = req->n_channels;
} else { } else {
do { do {
if (local->hw_scan_band == NUM_NL80211_BANDS) if (local->hw_scan_band == NUM_NL80211_BANDS)
return false; return false;
n_chans = 0; n_chans = &local->hw_scan_req->req.n_channels;
*n_chans = 0;
for (i = 0; i < req->n_channels; i++) { for (i = 0; i < req->n_channels; i++) {
if (req->channels[i]->band != if (req->channels[i]->band !=
local->hw_scan_band) local->hw_scan_band)
continue; continue;
local->hw_scan_req->req.channels[n_chans] = local->hw_scan_req->req.channels[(*n_chans)++] =
req->channels[i]; req->channels[i];
n_chans++;
bands_used |= BIT(req->channels[i]->band); bands_used |= BIT(req->channels[i]->band);
} }
local->hw_scan_band++; local->hw_scan_band++;
} while (!n_chans); } while (!*n_chans);
} }
local->hw_scan_req->req.n_channels = n_chans;
ieee80211_prepare_scan_chandef(&chandef); ieee80211_prepare_scan_chandef(&chandef);
if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT)
......
...@@ -1843,7 +1843,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1843,7 +1843,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* add interfaces */ /* add interfaces */
sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
if (sdata) { if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
/* in HW restart it exists already */ /* in HW restart it exists already */
WARN_ON(local->resuming); WARN_ON(local->resuming);
res = drv_add_interface(local, sdata); res = drv_add_interface(local, sdata);
......
...@@ -3416,10 +3416,14 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -3416,10 +3416,14 @@ int cfg80211_wext_siwscan(struct net_device *dev,
wiphy = &rdev->wiphy; wiphy = &rdev->wiphy;
/* Determine number of channels, needed to allocate creq */ /* Determine number of channels, needed to allocate creq */
if (wreq && wreq->num_channels) if (wreq && wreq->num_channels) {
/* Passed from userspace so should be checked */
if (unlikely(wreq->num_channels > IW_MAX_FREQUENCIES))
return -EINVAL;
n_channels = wreq->num_channels; n_channels = wreq->num_channels;
else } else {
n_channels = ieee80211_get_num_supported_channels(wiphy); n_channels = ieee80211_get_num_supported_channels(wiphy);
}
creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
n_channels * sizeof(void *), n_channels * sizeof(void *),
...@@ -3493,8 +3497,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -3493,8 +3497,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
creq->ssids[0].ssid_len = wreq->essid_len; creq->ssids[0].ssid_len = wreq->essid_len;
} }
if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) {
creq->ssids = NULL;
creq->n_ssids = 0; creq->n_ssids = 0;
}
} }
for (i = 0; i < NUM_NL80211_BANDS; i++) for (i = 0; i < NUM_NL80211_BANDS; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment