diff options
author | Brian Norris <briannorris@chromium.org> | 2016-11-18 19:30:26 +0530 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2016-11-19 09:18:48 +0200 |
commit | 4a79aa17d53ea8d5fa4acdaed487a786a185936a (patch) | |
tree | 17fac95b50f4108fc9edad96275494b534f1cd42 /drivers/net/wireless/marvell/mwifiex/pcie.h | |
parent | 6712076883ca49532b4e15216fb69cde69a5a919 (diff) | |
download | linux-4a79aa17d53ea8d5fa4acdaed487a786a185936a.tar.bz2 |
mwifiex: resolve races between async FW init (failure) and device removal
It's possible for the FW init sequence to fail, which will trigger a
device cleanup sequence in mwifiex_fw_dpc(). This sequence can race with
device suspend() or remove() (e.g., reboot or unbind), and can trigger
use-after-free issues. Currently, this driver attempts (poorly) to
synchronize remove() using a semaphore, but it doesn't protect some of
the critical sections properly. Particularly, we grab a pointer to the
adapter struct (card->adapter) without checking if it's being freed or
not. We later do a NULL check on the adapter, but that doesn't work if
the adapter was freed.
Also note that the PCIe interface driver doesn't ever set card->adapter
to NULL, so even if we get the synchronization right, we still might try
to redo the cleanup in ->remove(), even if the FW init failure sequence
already did it.
This patch replaces the static semaphore with a per-device completion
struct, and uses that completion to synchronize the remove() thread with
the mwifiex_fw_dpc(). A future patch will utilize this completion to
synchronize the suspend() thread as well.
Signed-off-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/marvell/mwifiex/pcie.h')
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/pcie.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 46f99cae9399..ae3365d1c34e 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -22,6 +22,7 @@ #ifndef _MWIFIEX_PCIE_H #define _MWIFIEX_PCIE_H +#include <linux/completion.h> #include <linux/pci.h> #include <linux/interrupt.h> @@ -345,6 +346,7 @@ struct pcie_service_card { struct pci_dev *dev; struct mwifiex_adapter *adapter; struct mwifiex_pcie_device pcie; + struct completion fw_done; u8 txbd_flush; u32 txbd_wrptr; |