aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-20 15:36:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-28 14:40:25 -0400
commit01a0ac417ce9b4f1216a266f2fd454cffefc5aee (patch)
tree3bc13cf46eebc77a44e65b16132d26f71b131f50 /net/wireless/scan.c
parent40ba60ddfeff8ef42fb33c0bdacfbb5f83e96b32 (diff)
cfg80211: check lost scans later, fix bug
When we lose a scan, cfg80211 tries to clean up after the driver. However, it currently does this too early, it does this in GOING_DOWN already instead of DOWN, so it may happen with mac80211. Besides fixing this, also make it more robust by leaking the scan request so if the driver later actually finishes the scan, it won't crash. Also check in ___cfg80211_scan_done whether a scan request is still pending and exit if not. Reported-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Tested-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fe575a24c95c..7043de6221ab 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -18,7 +18,7 @@
18 18
19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) 19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
20 20
21void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) 21void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
22{ 22{
23 struct cfg80211_scan_request *request; 23 struct cfg80211_scan_request *request;
24 struct net_device *dev; 24 struct net_device *dev;
@@ -26,8 +26,13 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
26 union iwreq_data wrqu; 26 union iwreq_data wrqu;
27#endif 27#endif
28 28
29 ASSERT_RDEV_LOCK(rdev);
30
29 request = rdev->scan_req; 31 request = rdev->scan_req;
30 32
33 if (!request)
34 return;
35
31 dev = request->dev; 36 dev = request->dev;
32 37
33 /* 38 /*
@@ -53,7 +58,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
53 dev_put(dev); 58 dev_put(dev);
54 59
55 rdev->scan_req = NULL; 60 rdev->scan_req = NULL;
56 kfree(request); 61
62 /*
63 * OK. If this is invoked with "leak" then we can't
64 * free this ... but we've cleaned it up anyway. The
65 * driver failed to call the scan_done callback, so
66 * all bets are off, it might still be trying to use
67 * the scan request or not ... if it accesses the dev
68 * in there (it shouldn't anyway) then it may crash.
69 */
70 if (!leak)
71 kfree(request);
57} 72}
58 73
59void __cfg80211_scan_done(struct work_struct *wk) 74void __cfg80211_scan_done(struct work_struct *wk)
@@ -64,7 +79,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
64 scan_done_wk); 79 scan_done_wk);
65 80
66 cfg80211_lock_rdev(rdev); 81 cfg80211_lock_rdev(rdev);
67 ___cfg80211_scan_done(rdev); 82 ___cfg80211_scan_done(rdev, false);
68 cfg80211_unlock_rdev(rdev); 83 cfg80211_unlock_rdev(rdev);
69} 84}
70 85