We observed a SHUTDOWN command timeout during reboot stress test due to a corner case firmware bug. It leads to use-after-free on adapter structure pointer and crash. Let's add MWIFIEX_IFACE_WORK_DONT_RUN work flag to avoid executing any work scheduled after cancel_work_sync() call in teardown path to resolve the issue. Signed-off-by: Amitkumar Karwar <akarwar@xxxxxxxxxxx> --- v2: New work_flag has been added to resolve the issue cleanly as per Brian's suggestion. --- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++++ drivers/net/wireless/marvell/mwifiex/sdio.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 5c82972..d5b1fd6 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -510,6 +510,7 @@ struct mwifiex_roc_cfg { enum mwifiex_iface_work_flags { MWIFIEX_IFACE_WORK_DEVICE_DUMP, MWIFIEX_IFACE_WORK_CARD_RESET, + MWIFIEX_IFACE_WORK_DONT_RUN, }; struct mwifiex_private { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a0d9180..bb3d798 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -294,6 +294,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) if (!adapter || !adapter->priv_num) return; + set_bit(MWIFIEX_IFACE_WORK_DONT_RUN, &card->work_flags); cancel_work_sync(&card->work); reg = card->pcie.reg; @@ -2721,6 +2722,9 @@ static void mwifiex_pcie_work(struct work_struct *work) struct pcie_service_card *card = container_of(work, struct pcie_service_card, work); + if (test_bit(MWIFIEX_IFACE_WORK_DONT_RUN, &card->work_flags)) + return; + if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags)) mwifiex_pcie_device_dump_work(card->adapter); diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index a4b356d..8140bb4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -387,6 +387,7 @@ static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) if (!adapter || !adapter->priv_num) return; + set_bit(MWIFIEX_IFACE_WORK_DONT_RUN, &card->work_flags); cancel_work_sync(&card->work); mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num); @@ -2514,6 +2515,9 @@ static void mwifiex_sdio_work(struct work_struct *work) struct sdio_mmc_card *card = container_of(work, struct sdio_mmc_card, work); + if (test_bit(MWIFIEX_IFACE_WORK_DONT_RUN, &card->work_flags)) + return; + if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags)) mwifiex_sdio_device_dump_work(card->adapter); -- 1.9.1