linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Brian Norris <briannorris@chromium.org>
To: Ganapathi Bhat <gbhat@marvell.com>
Cc: linux-wireless@vger.kernel.org, Cathy Luo <cluo@marvell.com>,
	Xinming Hu <huxm@marvell.com>, Zhiyuan Yang <yangzy@marvell.com>,
	James Cao <jcao@marvell.com>,
	Mangesh Malusare <mmangesh@marvell.com>,
	Douglas Anderson <dianders@chromium.org>,
	Karthik Ananthapadmanabha <karthida@marvell.com>
Subject: Re: [PATCH 3/3] mwifiex: cleanup rx_reorder_tbl_lock usage
Date: Mon, 6 Nov 2017 18:30:50 -0800	[thread overview]
Message-ID: <20171107023049.GB42502@google.com> (raw)
In-Reply-To: <1509442967-14149-4-git-send-email-gbhat@marvell.com>

Hi,

I haven't reviewed this patch in its entirety, but I'm pretty sure
you're introducing a reliable AA deadlock. See below.

Are you sure you're actually testing these codepaths?

On Tue, Oct 31, 2017 at 03:12:47PM +0530, Ganapathi Bhat wrote:
> From: Karthik Ananthapadmanabha <karthida@marvell.com>
> 
> Fix the incorrect usage of rx_reorder_tbl_lock spinlock:
> 
> 1. We shouldn't access the fields of the elements returned by
> mwifiex_11n_get_rx_reorder_tbl() after we have released spin
> lock. To fix this, To fix this, aquire the spinlock before
> calling this function and release the lock only after processing
> the corresponding element is complete.
> 
> 2. Realsing the spinlock during iteration of the list and holding
> it back before next iteration is unsafe. Fix it by releasing the
> lock only after iteration of the list is complete.
> 
> Signed-off-by: Karthik Ananthapadmanabha <karthida@marvell.com>
> Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> ---
>  .../net/wireless/marvell/mwifiex/11n_rxreorder.c   | 34 +++++++++++++++++-----
>  drivers/net/wireless/marvell/mwifiex/uap_txrx.c    |  3 ++
>  2 files changed, 29 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> index 4631bc2..b99ace8 100644
> --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> @@ -234,23 +234,19 @@ static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
>  
>  /*
>   * This function returns the pointer to an entry in Rx reordering
> - * table which matches the given TA/TID pair.
> + * table which matches the given TA/TID pair. The caller must
> + * hold rx_reorder_tbl_lock, before calling this function.
>   */
>  struct mwifiex_rx_reorder_tbl *
>  mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
>  {
>  	struct mwifiex_rx_reorder_tbl *tbl;
> -	unsigned long flags;
>  
> -	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
>  		if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
> -			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
> -					       flags);
>  			return tbl;
>  		}
>  	}
> -	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  
>  	return NULL;
>  }
> @@ -355,11 +351,14 @@ void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
>  	 * If we get a TID, ta pair which is already present dispatch all the
>  	 * the packets and move the window size until the ssn
>  	 */
> +	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
>  	if (tbl) {
>  		mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num);
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  		return;
>  	}
> +	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  	/* if !tbl then create one */
>  	new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL);
>  	if (!new_node)
> @@ -571,15 +570,19 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
>  	u16 pkt_index;
>  	bool init_window_shift = false;
>  	int ret = 0;
> +	unsigned long flags;
>  
> +	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
>  	if (!tbl) {
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  		if (pkt_type != PKT_TYPE_BAR)
>  			mwifiex_11n_dispatch_pkt(priv, payload);
>  		return ret;
>  	}
>  
>  	if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  		mwifiex_11n_dispatch_pkt(priv, payload);
>  		return ret;
>  	}
> @@ -666,6 +669,8 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
>  	if (!tbl->timer_context.timer_is_set ||
>  	    prev_start_win != tbl->start_win)
>  		mwifiex_11n_rxreorder_timer_restart(tbl);
> +
> +	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  	return ret;
>  }
>  
> @@ -683,6 +688,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
>  	struct mwifiex_ra_list_tbl *ra_list;
>  	u8 cleanup_rx_reorder_tbl;
>  	int tid_down;
> +	unsigned long flags;
>  
>  	if (type == TYPE_DELBA_RECEIVE)
>  		cleanup_rx_reorder_tbl = (initiator) ? true : false;
> @@ -693,14 +699,18 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
>  		    peer_mac, tid, initiator);
>  
>  	if (cleanup_rx_reorder_tbl) {
> +		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  		tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
>  								 peer_mac);
>  		if (!tbl) {
> +			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
> +					       flags);
>  			mwifiex_dbg(priv->adapter, EVENT,
>  				    "event: TID, TA not found in table\n");
>  			return;
>  		}
>  		mwifiex_del_rx_reorder_entry(priv, tbl);
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  	} else {
>  		ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
>  		if (!ptx_tbl) {
> @@ -732,6 +742,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
>  	int tid, win_size;
>  	struct mwifiex_rx_reorder_tbl *tbl;
>  	uint16_t block_ack_param_set;
> +	unsigned long flags;
>  
>  	block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
>  
> @@ -745,17 +756,20 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
>  		mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n",
>  			    add_ba_rsp->peer_mac_addr, tid);
>  
> +		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  		tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
>  						     add_ba_rsp->peer_mac_addr);
>  		if (tbl)
>  			mwifiex_del_rx_reorder_entry(priv, tbl);
>  
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  		return 0;
>  	}
>  
>  	win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
>  		    >> BLOCKACKPARAM_WINSIZE_POS;
>  
> +	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
>  					     add_ba_rsp->peer_mac_addr);
>  	if (tbl) {
> @@ -766,6 +780,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
>  		else
>  			tbl->amsdu = false;
>  	}
> +	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  
>  	mwifiex_dbg(priv->adapter, CMD,
>  		    "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
> @@ -806,9 +821,7 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
>  	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);

^^ Acquisition

>  	list_for_each_entry_safe(del_tbl_ptr, tmp_node,
>  				 &priv->rx_reorder_tbl_ptr, list) {
> -		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);

^^ No longer dropping the lock

>  		mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);

^^ This function also acquires the lock

Deadlock!

Brian

> -		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	}
>  	INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
>  	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
> @@ -933,6 +946,7 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
>  	int tlv_buf_left = len;
>  	int ret;
>  	u8 *tmp;
> +	unsigned long flags;
>  
>  	mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:",
>  			 event_buf, len);
> @@ -952,14 +966,18 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
>  			    tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num,
>  			    tlv_bitmap_len);
>  
> +		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  		rx_reor_tbl_ptr =
>  			mwifiex_11n_get_rx_reorder_tbl(priv, tlv_rxba->tid,
>  						       tlv_rxba->mac);
>  		if (!rx_reor_tbl_ptr) {
> +			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
> +					       flags);
>  			mwifiex_dbg(priv->adapter, ERROR,
>  				    "Can not find rx_reorder_tbl!");
>  			return;
>  		}
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  
>  		for (i = 0; i < tlv_bitmap_len; i++) {
>  			for (j = 0 ; j < 8; j++) {
> diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
> index 1e6a62c..21dc14f 100644
> --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
> +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
> @@ -421,12 +421,15 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
>  		spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
>  	}
>  
> +	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
>  	if (!priv->ap_11n_enabled ||
>  	    (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
>  	    (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
> +		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  		ret = mwifiex_handle_uap_rx_forward(priv, skb);
>  		return ret;
>  	}
> +	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
>  
>  	/* Reorder and send to kernel */
>  	pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
> -- 
> 1.9.1
> 

      reply	other threads:[~2017-11-07  2:30 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-31  9:42 [PATCH 0/3] mwifiex: fix usage issues with spinlocks Ganapathi Bhat
2017-10-31  9:42 ` [PATCH 1/3] mwifiex: cleanup rx_pkt_lock usage in 11n_rxreorder.c Ganapathi Bhat
2017-11-01 21:28   ` Brian Norris
2017-11-02 10:30     ` [EXT] " Ganapathi Bhat
2017-11-07  0:42       ` Doug Anderson
2017-11-07  2:25         ` Brian Norris
2017-11-07 16:25           ` Ganapathi Bhat
2017-11-07 21:15             ` Doug Anderson
2017-12-07 10:29               ` Ganapathi Bhat
2018-06-25  9:49                 ` Ganapathi Bhat
2017-11-07 21:13           ` Doug Anderson
2017-10-31  9:42 ` [PATCH 2/3] mwifiex: cleanup tx_ba_stream_tbl_lock usage Ganapathi Bhat
2017-10-31  9:42 ` [PATCH 3/3] mwifiex: cleanup rx_reorder_tbl_lock usage Ganapathi Bhat
2017-11-07  2:30   ` Brian Norris [this message]

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=20171107023049.GB42502@google.com \
    --to=briannorris@chromium.org \
    --cc=cluo@marvell.com \
    --cc=dianders@chromium.org \
    --cc=gbhat@marvell.com \
    --cc=huxm@marvell.com \
    --cc=jcao@marvell.com \
    --cc=karthida@marvell.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=mmangesh@marvell.com \
    --cc=yangzy@marvell.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).