All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Norris <briannorris@chromium.org>
To: Xinming Hu <huxinming820@gmail.com>
Cc: Linux Wireless <linux-wireless@vger.kernel.org>,
	Kalle Valo <kvalo@qca.qualcomm.com>,
	Dmitry Torokhov <dtor@google.com>,
	Amitkumar Karwar <akarwar@marvell.com>,
	Cathy Luo <cluo@marvell.com>
Subject: Re: [PATCH RESEND v2 03/11] mwifiex: resolve races between async FW init (failure) and device removal
Date: Thu, 10 Nov 2016 10:37:24 -0800	[thread overview]
Message-ID: <20161110183723.GA134624@google.com> (raw)
In-Reply-To: <1478779032-5165-3-git-send-email-huxinming820@marvell.com>

Hi,

On Thu, Nov 10, 2016 at 07:57:04PM +0800, Xinming Hu wrote:
> From: Brian Norris <briannorris@chromium.org>
> 
> 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>
> ---
> v2: Same as v1
> ---
>  drivers/net/wireless/marvell/mwifiex/main.c | 46 ++++++++++-------------------
>  drivers/net/wireless/marvell/mwifiex/main.h | 13 +++++---
>  drivers/net/wireless/marvell/mwifiex/pcie.c | 18 +++++------
>  drivers/net/wireless/marvell/mwifiex/pcie.h |  2 ++
>  drivers/net/wireless/marvell/mwifiex/sdio.c | 18 +++++------
>  drivers/net/wireless/marvell/mwifiex/sdio.h |  2 ++
>  drivers/net/wireless/marvell/mwifiex/usb.c  | 23 +++++++--------
>  drivers/net/wireless/marvell/mwifiex/usb.h  |  2 ++
>  8 files changed, 55 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index c710d5e..09d46d6 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -521,7 +521,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
>  	struct mwifiex_private *priv;
>  	struct mwifiex_adapter *adapter = context;
>  	struct mwifiex_fw_image fw;
> -	struct semaphore *sem = adapter->card_sem;
>  	bool init_failed = false;
>  	struct wireless_dev *wdev;
>  
> @@ -670,7 +669,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
>  	}
>  	if (init_failed)
>  		mwifiex_free_adapter(adapter);
> -	up(sem);
> +	/* Tell all current and future waiters we're finished */
> +	complete_all(adapter->fw_done);

This part introduces a new use-after-free. We need to dereference
adapter->fw_done *before* we free the adapter in mwifiex_free_adapter().
So you need a diff that looks something like this:

--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -514,6 +514,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	struct mwifiex_fw_image fw;
 	bool init_failed = false;
 	struct wireless_dev *wdev;
+	struct completion *fw_done = adapter->fw_done;
 
 	if (!firmware) {
 		mwifiex_dbg(adapter, ERROR,
@@ -654,7 +655,7 @@ done:
 	if (init_failed)
 		mwifiex_free_adapter(adapter);
 	/* Tell all current and future waiters we're finished */
-	complete_all(adapter->fw_done);
+	complete_all(fw_done);
 	return;
 }

 
Brian

>  	return;
>  }
>  
...

  reply	other threads:[~2016-11-10 18:37 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-10 11:57 [PATCH RESEND v2 01/11] mwifiex: check tx_hw_pending before downloading sleep confirm Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 02/11] mwifiex: complete blocked power save handshake in main process Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 03/11] mwifiex: resolve races between async FW init (failure) and device removal Xinming Hu
2016-11-10 18:37   ` Brian Norris [this message]
2016-11-11 13:06     ` Amitkumar Karwar
2016-11-10 11:57 ` [PATCH RESEND v2 04/11] mwifiex: remove redundant pdev check in suspend/resume handlers Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 05/11] mwifiex: don't pretend to resume while remove()'ing Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 06/11] mwifiex: resolve suspend() race with async FW init failure Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 07/11] mwifiex: reset card->adapter during device unregister Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 08/11] mwifiex: usb: handle HS failures Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 09/11] mwifiex: sdio: don't check for NULL sdio_func Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 10/11] mwifiex: stop checking for NULL drvata/intfdata Xinming Hu
2016-11-10 11:57 ` [PATCH RESEND v2 11/11] mwifiex: pcie: stop checking for NULL adapter->card Xinming Hu
2016-11-10 14:06 ` [PATCH RESEND v2 01/11] mwifiex: check tx_hw_pending before downloading sleep confirm Kalle Valo
2016-11-11 13:09   ` Amitkumar Karwar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161110183723.GA134624@google.com \
    --to=briannorris@chromium.org \
    --cc=akarwar@marvell.com \
    --cc=cluo@marvell.com \
    --cc=dtor@google.com \
    --cc=huxinming820@gmail.com \
    --cc=kvalo@qca.qualcomm.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.