Re: [PATCH] cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()

2018-12-19 Thread Kalle Valo
Jia-Ju Bai  wrote:

> The function cw1200_bss_info_changed() and cw1200_hw_scan() can be
> concurrently executed.
> The two functions both access a possible shared variable "frame.skb".
> 
> This shared variable is freed by dev_kfree_skb() in cw1200_upload_beacon(), 
> which is called by cw1200_bss_info_changed(). The free operation is 
> protected by a mutex lock "priv->conf_mutex" in cw1200_bss_info_changed().
> 
> In cw1200_hw_scan(), this shared variable is accessed without the
> protection of the mutex lock "priv->conf_mutex". 
> Thus, concurrency use-after-free bugs may occur.
> 
> To fix these bugs, the original calls to mutex_lock(&priv->conf_mutex) and 
> mutex_unlock(&priv->conf_mutex) are moved to the places, which can 
> protect the accesses to the shared variable.
> 
> Signed-off-by: Jia-Ju Bai 

Patch applied to wireless-drivers-next.git, thanks.

4f68ef64cd7f cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()

-- 
https://patchwork.kernel.org/patch/10730469/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



[PATCH] cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()

2018-12-13 Thread Jia-Ju Bai
The function cw1200_bss_info_changed() and cw1200_hw_scan() can be
concurrently executed.
The two functions both access a possible shared variable "frame.skb".

This shared variable is freed by dev_kfree_skb() in cw1200_upload_beacon(), 
which is called by cw1200_bss_info_changed(). The free operation is 
protected by a mutex lock "priv->conf_mutex" in cw1200_bss_info_changed().

In cw1200_hw_scan(), this shared variable is accessed without the
protection of the mutex lock "priv->conf_mutex". 
Thus, concurrency use-after-free bugs may occur.

To fix these bugs, the original calls to mutex_lock(&priv->conf_mutex) and 
mutex_unlock(&priv->conf_mutex) are moved to the places, which can 
protect the accesses to the shared variable.

Signed-off-by: Jia-Ju Bai 
---
 drivers/net/wireless/st/cw1200/scan.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/st/cw1200/scan.c 
b/drivers/net/wireless/st/cw1200/scan.c
index 67213f11acbd..0a9eac93dd01 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -78,6 +78,10 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
return -EINVAL;
 
+   /* will be unlocked in cw1200_scan_work() */
+   down(&priv->scan.lock);
+   mutex_lock(&priv->conf_mutex);
+
frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
req->ie_len);
if (!frame.skb)
@@ -86,19 +90,15 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
if (req->ie_len)
skb_put_data(frame.skb, req->ie, req->ie_len);
 
-   /* will be unlocked in cw1200_scan_work() */
-   down(&priv->scan.lock);
-   mutex_lock(&priv->conf_mutex);
-
ret = wsm_set_template_frame(priv, &frame);
if (!ret) {
/* Host want to be the probe responder. */
ret = wsm_set_probe_responder(priv, true);
}
if (ret) {
+   dev_kfree_skb(frame.skb);
mutex_unlock(&priv->conf_mutex);
up(&priv->scan.lock);
-   dev_kfree_skb(frame.skb);
return ret;
}
 
@@ -120,10 +120,9 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
++priv->scan.n_ssids;
}
 
-   mutex_unlock(&priv->conf_mutex);
-
if (frame.skb)
dev_kfree_skb(frame.skb);
+   mutex_unlock(&priv->conf_mutex);
queue_work(priv->workqueue, &priv->scan.work);
return 0;
 }
-- 
2.17.0