From 8bd2c1ead5e2b67270aedfc95dcac8d6955db4e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 22 Sep 2011 15:14:54 -0700 Subject: [PATCH] iwlagn: fix dangling scan request If iwl_scan_initiate() fails for any reason, priv->scan_request and priv->scan_vif are left dangling. This can lead to a crash later when iwl_bg_scan_completed() tries to run a pending scan request. In practice, this seems to be very rare due to the STATUS_SCANNING check earlier. That check, however, is wrong -- it should allow a scan to be queued when a reset/roc scan is going on. When a normal scan is already going on, a new one can't be issued by mac80211, so that code can be removed completely. I introduced this bug when adding off-channel support in commit 266af4c745952e9bebf687dd68af58df553cb59d. Cc: stable@kernel.org [3.0] Reported-by: Peng Yan Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 07af6ec8d9d2..74204ec5b267 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -874,31 +874,33 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && - priv->scan_type != IWL_SCAN_NORMAL) { - IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); - ret = -EAGAIN; - goto out_unlock; - } - - /* mac80211 will only ask for one band at a time */ - priv->scan_request = req; - priv->scan_vif = vif; - /* * If an internal scan is in progress, just set * up the scan_request as per above. */ if (priv->scan_type != IWL_SCAN_NORMAL) { - IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); + IWL_DEBUG_SCAN(priv, + "SCAN request during internal scan - defer\n"); + priv->scan_request = req; + priv->scan_vif = vif; ret = 0; - } else + } else { + priv->scan_request = req; + priv->scan_vif = vif; + /* + * mac80211 will only ask for one band at a time + * so using channels[0] here is ok + */ ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, req->channels[0]->band); + if (ret) { + priv->scan_request = NULL; + priv->scan_vif = NULL; + } + } IWL_DEBUG_MAC80211(priv, "leave\n"); -out_unlock: mutex_unlock(&priv->shrd->mutex); return ret; -- 2.11.0