aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-03-19 10:04:07 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-03-24 06:15:58 -0400
commitf9f475292dbb0e7035fb6661d1524761ea0888d9 (patch)
tree77f4bf7741deb74108ef033eeb68131069a8e406 /net/wireless/scan.c
parent8b305780ed0c49a49c6bd58a4372fd6b22a5a71e (diff)
cfg80211: always check for scan end on P2P device
If a P2P device wdev is removed while it has a scan, then the scan completion might crash later as it is already freed by that time. To avoid the crash always check the scan completion when the P2P device is being removed for some reason. If the driver already canceled it, don't want and free it, otherwise warn and leak it to avoid later crashes. In order to do this, locking needs to be changed away from the rdev mutex (which can't always be guaranteed). For now, use the sched_scan_mtx instead, I'll rename it to just scan_mtx in a later patch. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index e93bd31d23bb..fd99ea495b7e 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
169 union iwreq_data wrqu; 169 union iwreq_data wrqu;
170#endif 170#endif
171 171
172 ASSERT_RDEV_LOCK(rdev); 172 lockdep_assert_held(&rdev->sched_scan_mtx);
173 173
174 request = rdev->scan_req; 174 request = rdev->scan_req;
175 175
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
230 rdev = container_of(wk, struct cfg80211_registered_device, 230 rdev = container_of(wk, struct cfg80211_registered_device,
231 scan_done_wk); 231 scan_done_wk);
232 232
233 cfg80211_lock_rdev(rdev); 233 mutex_lock(&rdev->sched_scan_mtx);
234 ___cfg80211_scan_done(rdev, false); 234 ___cfg80211_scan_done(rdev, false);
235 cfg80211_unlock_rdev(rdev); 235 mutex_unlock(&rdev->sched_scan_mtx);
236} 236}
237 237
238void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 238void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -1062,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1062 if (IS_ERR(rdev)) 1062 if (IS_ERR(rdev))
1063 return PTR_ERR(rdev); 1063 return PTR_ERR(rdev);
1064 1064
1065 mutex_lock(&rdev->sched_scan_mtx);
1065 if (rdev->scan_req) { 1066 if (rdev->scan_req) {
1066 err = -EBUSY; 1067 err = -EBUSY;
1067 goto out; 1068 goto out;
@@ -1168,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1168 dev_hold(dev); 1169 dev_hold(dev);
1169 } 1170 }
1170 out: 1171 out:
1172 mutex_unlock(&rdev->sched_scan_mtx);
1171 kfree(creq); 1173 kfree(creq);
1172 cfg80211_unlock_rdev(rdev); 1174 cfg80211_unlock_rdev(rdev);
1173 return err; 1175 return err;