mac80211: fix scan band off-by-one error
authorJohannes Berg <johannes@sipsolutions.net>
Mon, 28 Jan 2008 16:08:56 +0000 (17:08 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 29 Feb 2008 20:19:32 +0000 (15:19 -0500)
When checking for the next band to advance to, there
was an off-by-one error that could lead to an access
to an invalid array index. Additionally, the later
check for scan_band >= IEEE80211_NUM_BANDS is not
required since that will never be true.

This also improves the comments related to that code.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/ieee80211_sta.c

index 2628222..0d5e3fe 100644 (file)
@@ -3412,22 +3412,28 @@ void ieee80211_sta_scan_work(struct work_struct *work)
 
        switch (local->scan_state) {
        case SCAN_SET_CHANNEL:
-               /* get current scan band */
+               /*
+                * Get current scan band. scan_band may be IEEE80211_NUM_BANDS
+                * after we successfully scanned the last channel of the last
+                * band (and the last band is supported by the hw)
+                */
                if (local->scan_band < IEEE80211_NUM_BANDS)
                        sband = local->hw.wiphy->bands[local->scan_band];
                else
                        sband = NULL;
 
-               /* if we started at an unsupported one, advance */
-               while (!sband && local->scan_band < IEEE80211_NUM_BANDS) {
+               /*
+                * If we are at an unsupported band and have more bands
+                * left to scan, advance to the next supported one.
+                */
+               while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) {
                        local->scan_band++;
                        sband = local->hw.wiphy->bands[local->scan_band];
                        local->scan_channel_idx = 0;
                }
 
-               if (!sband ||
-                   (local->scan_channel_idx >= sband->n_channels &&
-                    local->scan_band >= IEEE80211_NUM_BANDS)) {
+               /* if no more bands/channels left, complete scan */
+               if (!sband || local->scan_channel_idx >= sband->n_channels) {
                        ieee80211_scan_completed(local_to_hw(local));
                        return;
                }
@@ -3449,8 +3455,14 @@ void ieee80211_sta_scan_work(struct work_struct *work)
                        }
                }
 
+               /* advance state machine to next channel/band */
                local->scan_channel_idx++;
                if (local->scan_channel_idx >= sband->n_channels) {
+                       /*
+                        * scan_band may end up == IEEE80211_NUM_BANDS, but
+                        * we'll catch that case above and complete the scan
+                        * if that is the case.
+                        */
                        local->scan_band++;
                        local->scan_channel_idx = 0;
                }