2018-12-14 03:56:34

by Jia-Ju Bai

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

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 <[email protected]>
---
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



2018-12-20 08:26:11

by Kalle Valo

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

Jia-Ju Bai <[email protected]> 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 <[email protected]>

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