aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2014-12-15 06:25:38 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-12-18 08:38:09 -0500
commit31a60ed1e95ab8afbadb65599bef12b195080a0c (patch)
tree0be2e75a0554a2c1e1c01c6708af80c7388b6e74 /net/wireless/scan.c
parent0f8b82456178d558f14011e06ebf9af937c4b197 (diff)
nl80211: Convert sched_scan_req pointer to RCU pointer
Because of possible races when accessing sched_scan_req pointer in rdev, the sched_scan_req is converted to RCU pointer. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index bda39f149810..c705c3e2b751 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -257,7 +257,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
257 257
258 rtnl_lock(); 258 rtnl_lock();
259 259
260 request = rdev->sched_scan_req; 260 request = rtnl_dereference(rdev->sched_scan_req);
261 261
262 /* we don't have sched_scan_req anymore if the scan is stopping */ 262 /* we don't have sched_scan_req anymore if the scan is stopping */
263 if (request) { 263 if (request) {
@@ -279,7 +279,8 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy)
279{ 279{
280 trace_cfg80211_sched_scan_results(wiphy); 280 trace_cfg80211_sched_scan_results(wiphy);
281 /* ignore if we're not scanning */ 281 /* ignore if we're not scanning */
282 if (wiphy_to_rdev(wiphy)->sched_scan_req) 282
283 if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req))
283 queue_work(cfg80211_wq, 284 queue_work(cfg80211_wq,
284 &wiphy_to_rdev(wiphy)->sched_scan_results_wk); 285 &wiphy_to_rdev(wiphy)->sched_scan_results_wk);
285} 286}
@@ -308,6 +309,7 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
308int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, 309int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
309 bool driver_initiated) 310 bool driver_initiated)
310{ 311{
312 struct cfg80211_sched_scan_request *sched_scan_req;
311 struct net_device *dev; 313 struct net_device *dev;
312 314
313 ASSERT_RTNL(); 315 ASSERT_RTNL();
@@ -315,7 +317,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
315 if (!rdev->sched_scan_req) 317 if (!rdev->sched_scan_req)
316 return -ENOENT; 318 return -ENOENT;
317 319
318 dev = rdev->sched_scan_req->dev; 320 sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
321 dev = sched_scan_req->dev;
319 322
320 if (!driver_initiated) { 323 if (!driver_initiated) {
321 int err = rdev_sched_scan_stop(rdev, dev); 324 int err = rdev_sched_scan_stop(rdev, dev);
@@ -325,8 +328,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
325 328
326 nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); 329 nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
327 330
328 kfree(rdev->sched_scan_req); 331 RCU_INIT_POINTER(rdev->sched_scan_req, NULL);
329 rdev->sched_scan_req = NULL; 332 kfree_rcu(sched_scan_req, rcu_head);
330 333
331 return 0; 334 return 0;
332} 335}