diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-09-11 00:01:51 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-15 22:48:20 +0200 |
commit | 5bc75728fd43bb15b46f16ef465bcf9d487393cf (patch) | |
tree | 5732adee3965970390bf7953d214c757bbdba2a2 /net/mac80211/mlme.c | |
parent | mac80211: fix work race (diff) | |
download | linux-5bc75728fd43bb15b46f16ef465bcf9d487393cf.tar.xz linux-5bc75728fd43bb15b46f16ef465bcf9d487393cf.zip |
mac80211: fix scan vs. interface removal race
When we remove an interface, we can currently end up having
a pointer to it left in local->scan_sdata after it has been
set down, and then with a hardware scan the scan completion
can try to access it which is a bug. Alternatively, a scan
that started as a hardware scan may terminate as though it
was a software scan, if the timing is just right.
On SMP systems, software scan also has a similar problem,
just canceling the delayed work and setting a flag isn't
enough since it may be running concurrently; in this case
we would also never restore state of other interfaces.
This patch hopefully fixes the problems by always invoking
ieee80211_scan_completed or requiring it to be invoked by
the driver, I suspect the drivers that have ->hw_scan() are
buggy. The bug will not manifest itself unless you remove
the interface while hw-scanning which will also turn off
the hw, and then add a new interface which will be unusable
until you scan once.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9e20a0c20a46..19c7f21e49d1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2530,7 +2530,7 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_if_sta *ifsta; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata && sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && |