mwifiex: unregister wiphy before freeing resources
authorBrian Norris <briannorris@chromium.org>
Tue, 25 Jul 2017 01:13:21 +0000 (18:13 -0700)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 28 Jul 2017 14:47:47 +0000 (17:47 +0300)
It's possible for some control interfaces (e.g., scans, set freq) to be
active after we've stopped our main work queue and the netif TX queues.
These don't get completely shut out until we've unregistered the wdevs
and wiphy.

So let's only free command buffers and poison our lists after
wiphy_unregister().

This resolves various use-after-free issues seen when resetting the
device.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/marvell/mwifiex/init.c
drivers/net/wireless/marvell/mwifiex/main.c
drivers/net/wireless/marvell/mwifiex/main.h

index 3ecb59f7405b1fae27846ec0e52ffaa548a49bab..de96675e43d5aa224f7d0535e873b7a17e8a6394 100644 (file)
@@ -418,7 +418,10 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
        mwifiex_cancel_all_pending_cmd(adapter);
        wake_up_interruptible(&adapter->cmd_wait_q.wait);
        wake_up_interruptible(&adapter->hs_activate_wait_q);
+}
 
+void mwifiex_free_cmd_buffers(struct mwifiex_adapter *adapter)
+{
        /* Free lock variables */
        mwifiex_free_lock_list(adapter);
 
index 9c8f7bcfef8b998ac5fb15be3c8ebb12b4518a8a..77e49172066416bc981f73e8b32a4f55d130dbf7 100644 (file)
@@ -653,6 +653,7 @@ err_dnld_fw:
        if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
                pr_debug("info: %s: shutdown mwifiex\n", __func__);
                mwifiex_shutdown_drv(adapter);
+               mwifiex_free_cmd_buffers(adapter);
        }
 
        init_failed = true;
@@ -1404,11 +1405,13 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
                        mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
                rtnl_unlock();
        }
-       vfree(adapter->chan_stats);
 
        wiphy_unregister(adapter->wiphy);
        wiphy_free(adapter->wiphy);
        adapter->wiphy = NULL;
+
+       vfree(adapter->chan_stats);
+       mwifiex_free_cmd_buffers(adapter);
 }
 
 /*
@@ -1515,6 +1518,7 @@ err_kmalloc:
                mwifiex_dbg(adapter, ERROR,
                            "info: %s: shutdown mwifiex\n", __func__);
                mwifiex_shutdown_drv(adapter);
+               mwifiex_free_cmd_buffers(adapter);
        }
 
        complete_all(adapter->fw_done);
@@ -1662,6 +1666,7 @@ err_registerdev:
        if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
                pr_debug("info: %s: shutdown mwifiex\n", __func__);
                mwifiex_shutdown_drv(adapter);
+               mwifiex_free_cmd_buffers(adapter);
        }
 err_kmalloc:
        mwifiex_free_adapter(adapter);
index f8cf3079ac7dff01fce20834b9e2b2909cbe1899..62ce4e81f6952093cdf33f2f6fd30d74ba3c1b8a 100644 (file)
@@ -1078,6 +1078,7 @@ int mwifiex_get_debug_info(struct mwifiex_private *,
 
 int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);
 int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
+void mwifiex_free_cmd_buffers(struct mwifiex_adapter *adapter);
 void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
 void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
 void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter);