From 4a58e7c38443154fce1b47910e1a9184f65c5d72 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 5 Dec 2013 18:30:17 +0200 Subject: cfg80211: don't "leak" uncompleted scans ___cfg80211_scan_done() can be called in some cases (e.g. on NETDEV_DOWN) before the low level driver notified scan completion (which is indicated by passing leak=true). Clearing rdev->scan_req in this case is buggy, as scan_done_wk might have already being queued/running (and can't be flushed as it takes rtnl()). If a new scan will be requested at this stage, the scan_done_wk will try freeing it (instead of the previous scan), and this will later result in a use after free. Simply remove the "leak" option, and replace it with a standard WARN_ON. An example backtrace after such crash: Unable to handle kernel paging request at virtual address fffffee5 pgd = c0004000 [fffffee5] *pgd=9fdf6821, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] SMP ARM PC is at cfg80211_scan_done+0x28/0xc4 [cfg80211] LR is at __ieee80211_scan_completed+0xe4/0x2dc [mac80211] [] (cfg80211_scan_done+0x28/0xc4 [cfg80211]) [] (__ieee80211_scan_completed+0xe4/0x2dc [mac80211]) [] (ieee80211_scan_work+0x94/0x4f0 [mac80211]) [] (process_one_work+0x1b0/0x4a8) [] (worker_thread+0x138/0x37c) [] (kthread+0xa4/0xb0) Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/wireless/scan.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'net/wireless/scan.c') diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d4397eba5408..a32d52a04c27 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -161,7 +161,7 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, dev->bss_generation++; } -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) { struct cfg80211_scan_request *request; struct wireless_dev *wdev; @@ -210,17 +210,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) dev_put(wdev->netdev); rdev->scan_req = NULL; - - /* - * OK. If this is invoked with "leak" then we can't - * free this ... but we've cleaned it up anyway. The - * driver failed to call the scan_done callback, so - * all bets are off, it might still be trying to use - * the scan request or not ... if it accesses the dev - * in there (it shouldn't anyway) then it may crash. - */ - if (!leak) - kfree(request); + kfree(request); } void __cfg80211_scan_done(struct work_struct *wk) @@ -231,7 +221,7 @@ void __cfg80211_scan_done(struct work_struct *wk) scan_done_wk); rtnl_lock(); - ___cfg80211_scan_done(rdev, false); + ___cfg80211_scan_done(rdev); rtnl_unlock(); } -- cgit v1.2.1 From bdfbec2d2d240e9c528caae9c743801629b60166 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 9 Jan 2014 11:37:23 +0200 Subject: cfg80211: Add a function to get the number of supported channels Add a utility function to get the number of channels supported by the device, and update the places in the code that need this data. Signed-off-by: Ilan Peer [replace another occurrence in libertas, fix kernel-doc, fix bugs] Signed-off-by: Johannes Berg --- net/wireless/scan.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'net/wireless/scan.c') diff --git a/net/wireless/scan.c b/net/wireless/scan.c index a32d52a04c27..b528e31da2cf 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1089,11 +1089,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, /* Determine number of channels, needed to allocate creq */ if (wreq && wreq->num_channels) n_channels = wreq->num_channels; - else { - for (band = 0; band < IEEE80211_NUM_BANDS; band++) - if (wiphy->bands[band]) - n_channels += wiphy->bands[band]->n_channels; - } + else + n_channels = ieee80211_get_num_supported_channels(wiphy); creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + n_channels * sizeof(void *), -- cgit v1.2.1