diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2014-12-15 06:25:38 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-12-18 08:38:09 -0500 |
commit | 31a60ed1e95ab8afbadb65599bef12b195080a0c (patch) | |
tree | 0be2e75a0554a2c1e1c01c6708af80c7388b6e74 /net/wireless/scan.c | |
parent | 0f8b82456178d558f14011e06ebf9af937c4b197 (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.c | 13 |
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); | |||
308 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 309 | int __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 | } |