Re: [PATCH wireless-next 1/2] wifi: wfx: fix use-after-free of the cooling work on device removal
From: Sverdlin, Alexander
Date: Mon Sep 07 2026 - 05:17:26 EST
Hi Jérôme,
On Sun, 2026-09-06 at 22:47 +0200, Jérôme Pouiller wrote:
> When the device reports that it is too hot, wfx_suspend_hot_dev() blocks
> the Tx queues and arms cooling_timeout_work with a 10s delay. If the
> device recovers a normal temperature before the delay expires, the work
> is canceled. Else, the work declares the chip frozen and unblocks the Tx
> queues.
>
> However, this work is never canceled when the device is removed.
> cooling_timeout_work is queued on the system workqueue, while struct
> wfx_dev is released by wfx_free_common() (through ieee80211_free_hw()).
> So, if the device is unbound during this 10s window, the work fires
> after struct wfx_dev has been freed and dereferences it.
>
> Cancel the work during the teardown. It has to be done after
> wfx_bh_unregister(): the "device too hot" indication is processed by the
> bh, so canceling the work earlier would allow the bh to rearm it. On the
> other hand, the work calls wfx_tx_unlock(), which may in turn call
> wfx_bh_request_tx(). So it has to be canceled before bh_wq is destroyed.
>
> Note that the Tx queues are intentionally left blocked: the device is
> going away, so there is nothing to unblock.
>
> The issue was reported by the Sashiko review bot and the fix has been
> written by Copilot (including the commit log). The use-case is difficult
> to reproduce, so this code has not been tested. However, I don't believe
> this patch could cause any regression.
>
> Fixes: 1d52d29983e5d ("staging: wfx: add support for 'device too hot' indication")
> Assisted-by: Sashiko:gemini-3.1-pro-preview
> Assisted-by: Copilot:claude-opus-5
> Signed-off-by: Jérôme Pouiller <jerome.pouiller@xxxxxxxxxx>
thanks for the patch! Tested with rmmod, no regression visible,
Tested-by: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxxxx>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxxxx>
> ---
> drivers/net/wireless/silabs/wfx/main.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
> index 4e99fe7e5bb78..b6fd9d4c1f5fc 100644
> --- a/drivers/net/wireless/silabs/wfx/main.c
> +++ b/drivers/net/wireless/silabs/wfx/main.c
> @@ -487,6 +487,7 @@ int wfx_probe(struct wfx_dev *wdev)
> wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
> bh_unregister:
> wfx_bh_unregister(wdev);
> + cancel_delayed_work_sync(&wdev->cooling_timeout_work);
> destroy_workqueue(wdev->bh_wq);
> return err;
> }
> @@ -497,6 +498,7 @@ void wfx_release(struct wfx_dev *wdev)
> wfx_hif_shutdown(wdev);
> wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
> wfx_bh_unregister(wdev);
> + cancel_delayed_work_sync(&wdev->cooling_timeout_work);
> destroy_workqueue(wdev->bh_wq);
> }
--
Alexander Sverdlin
Siemens AG
www.siemens.com