linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
To: Larry Finger <Larry.Finger@lwfinger.net>
Cc: John W Linville <linville@tuxdriver.com>,
	"Hin-Tak Leung" <htl10@users.sourceforge.net>,
	linux-wireless@vger.kernel.org
Subject: Re: [PATCH] rtl8187: Use usb anchor facilities to manage urbs
Date: Tue, 9 Dec 2008 17:06:18 -0200	[thread overview]
Message-ID: <200812091706.19994.herton@mandriva.com.br> (raw)
In-Reply-To: <493e9dd9.dZux2YPGwepU1RUb%Larry.Finger@lwfinger.net>

Em Ter=E7a 09 Dezembro 2008, =E0s 14:33:29, Larry Finger escreveu:
> When SLUB debugging is enabled in the kernel, and the boot command in=
cludes
> the option "slub_debug=3DP", rtl8187 encounters a GPF due to a
> read-after-free of a urb.
>
> Following the example of changes in p54usb to fix the same problem, t=
he
> code has been modified to use the usb_anchor_urb() method. With this
> change, the USB core handles the freeing of urb's.
>
> This patch fixes the problem reported in Kernel Bugzilla #12185
> (http://bugzilla.kernel.org/show_bug.cgi?id=3D12185).
>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> Tested-by: Hin-Tak Leung <htl10@users.sourceforge.net>
> ---
>
> John,
>
> This problem has been in rtl8187 since its inclusion in mainline. As =
such,
> it probably doesn't matter when if gets included - 2.6.29 would be be=
st,
> but if you would prefer more testing, then 2.6.30 is OK. It does take
> special settings to trigger it.
>
> The relocation of the files for this driver to the
> drivers/net/wireless/rtl818x directory means that backporting this fi=
x to
> stable would require a different patch and is probably not worth the
> effort, but I'll leave that call to you.
>
> Larry
> ---

Hi, I looked at the patch and also the discussion on LKML about the p54=
usb,=20
just reading the patch now spotted some minor things, see below. Otherw=
ise=20
everything else looks fine.

>
> Index: wireless-testing/drivers/net/wireless/rtl818x/rtl8187.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- wireless-testing.orig/drivers/net/wireless/rtl818x/rtl8187.h
> +++ wireless-testing/drivers/net/wireless/rtl818x/rtl8187.h
> @@ -99,6 +99,7 @@ struct rtl8187_priv {
>  	struct ieee80211_supported_band band;
>  	struct usb_device *udev;
>  	u32 rx_conf;
> +	struct usb_anchor anchored;
>  	u16 txpwr_base;
>  	u8 asic_rev;
>  	u8 is_rtl8187b;
> @@ -115,7 +116,6 @@ struct rtl8187_priv {
>  	u8 aifsn[4];
>  	struct {
>  		__le64 buf;
> -		struct urb *urb;
>  		struct sk_buff_head queue;
>  	} b_tx_status;
>  };
> Index: wireless-testing/drivers/net/wireless/rtl818x/rtl8187_dev.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- wireless-testing.orig/drivers/net/wireless/rtl818x/rtl8187_dev.c
> +++ wireless-testing/drivers/net/wireless/rtl818x/rtl8187_dev.c
> @@ -99,7 +99,6 @@ static const struct ieee80211_channel rt
>  static void rtl8187_iowrite_async_cb(struct urb *urb)
>  {
>  	kfree(urb->context);
> -	usb_free_urb(urb);
>  }
>
>  static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 =
addr,
> @@ -136,11 +135,13 @@ static void rtl8187_iowrite_async(struct
>  	usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0=
),
>  			     (unsigned char *)dr, buf, len,
>  			     rtl8187_iowrite_async_cb, buf);
> +	usb_anchor_urb(urb, &priv->anchored);
>  	rc =3D usb_submit_urb(urb, GFP_ATOMIC);
>  	if (rc < 0) {
>  		kfree(buf);
> -		usb_free_urb(urb);
> +		usb_unanchor_urb(urb);
>  	}
> +	usb_free_urb(urb);
>  }
>
>  static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv=
,
> @@ -172,7 +173,6 @@ static void rtl8187_tx_cb(struct urb *ur
>  	struct ieee80211_hw *hw =3D info->rate_driver_data[0];
>  	struct rtl8187_priv *priv =3D hw->priv;
>
> -	usb_free_urb(info->rate_driver_data[1]);
>  	skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
>  					  sizeof(struct rtl8187_tx_hdr));
>  	ieee80211_tx_info_clear_status(info);
> @@ -273,11 +273,13 @@ static int rtl8187_tx(struct ieee80211_h
>
>  	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
>  			  buf, skb->len, rtl8187_tx_cb, skb);
> +	usb_anchor_urb(urb, &priv->anchored);
>  	rc =3D usb_submit_urb(urb, GFP_ATOMIC);
>  	if (rc < 0) {
> -		usb_free_urb(urb);
> +		usb_unanchor_urb(urb);
>  		kfree_skb(skb);
>  	}
> +	usb_free_urb(urb);
>
>  	return 0;
>  }
> @@ -301,14 +303,13 @@ static void rtl8187_rx_cb(struct urb *ur
>  		return;
>  	}
>  	spin_unlock(&priv->rx_queue.lock);
> +	skb_put(skb, urb->actual_length);
>
>  	if (unlikely(urb->status)) {
> -		usb_free_urb(urb);
>  		dev_kfree_skb_irq(skb);
>  		return;
>  	}
>
> -	skb_put(skb, urb->actual_length);
>  	if (!priv->is_rtl8187b) {
>  		struct rtl8187_rx_hdr *hdr =3D
>  			(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
> @@ -361,7 +362,6 @@ static void rtl8187_rx_cb(struct urb *ur
>
>  	skb =3D dev_alloc_skb(RTL8187_MAX_RX);
>  	if (unlikely(!skb)) {
> -		usb_free_urb(urb);
>  		/* TODO check rx queue length and refill *somewhere* */
>  		return;
>  	}

May be remove { } ? Probably checkpatch.pl didn't spot this because of =
the=20
comment using one line, but if it's allowed to keep {} in this case bec=
ause of=20
the comment no problem.

> @@ -373,24 +373,30 @@ static void rtl8187_rx_cb(struct urb *ur
>  	urb->context =3D skb;
>  	skb_queue_tail(&priv->rx_queue, skb);
>
> -	usb_submit_urb(urb, GFP_ATOMIC);
> +	usb_anchor_urb(urb, &priv->anchored);
> +	if (usb_submit_urb(urb, GFP_ATOMIC))
> +		usb_unanchor_urb(urb);

may be we should also skb_unlink and dev_kfree_skb_irq skb here like on=
=20
p54usb? although it should be freed anyway later on rtl8187_stop

>  }
>
>  static int rtl8187_init_urbs(struct ieee80211_hw *dev)
>  {
>  	struct rtl8187_priv *priv =3D dev->priv;
> -	struct urb *entry;
> +	struct urb *entry =3D NULL;
>  	struct sk_buff *skb;
>  	struct rtl8187_rx_info *info;
> +	int ret =3D 0;
>
>  	while (skb_queue_len(&priv->rx_queue) < 8) {
>  		skb =3D __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
> -		if (!skb)
> -			break;
> +		if (!skb) {
> +			ret =3D -ENOMEM;
> +			goto err;
> +		}
>  		entry =3D usb_alloc_urb(0, GFP_KERNEL);
>  		if (!entry) {
>  			kfree_skb(skb);

kfree_skb is also called after err: too now.

> -			break;
> +			ret =3D -ENOMEM;
> +			goto err;
>  		}
>  		usb_fill_bulk_urb(entry, priv->udev,
>  				  usb_rcvbulkpipe(priv->udev,
> @@ -401,10 +407,22 @@ static int rtl8187_init_urbs(struct ieee
>  		info->urb =3D entry;
>  		info->dev =3D dev;
>  		skb_queue_tail(&priv->rx_queue, skb);
> -		usb_submit_urb(entry, GFP_KERNEL);
> +		usb_anchor_urb(entry, &priv->anchored);
> +		ret =3D usb_submit_urb(entry, GFP_KERNEL);
> +		if (ret) {
> +			skb_unlink(skb, &priv->rx_queue);
> +			usb_unanchor_urb(entry);
> +			goto err;
> +		}
> +		usb_free_urb(entry);
>  	}
> +	return ret;
>
> -	return 0;
> +err:
> +	usb_free_urb(entry);
> +	kfree_skb(skb);
> +	usb_kill_anchored_urbs(&priv->anchored);
> +	return ret;
>  }
>
>  static void rtl8187b_status_cb(struct urb *urb)
> @@ -415,7 +433,6 @@ static void rtl8187b_status_cb(struct ur
>  	unsigned int cmd_type;
>
>  	if (unlikely(urb->status)) {
> -		usb_free_urb(urb);
>  		return;
>  	}

remove { }

>
> @@ -488,26 +505,32 @@ static void rtl8187b_status_cb(struct ur
>  		spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
>  	}
>
> -	usb_submit_urb(urb, GFP_ATOMIC);
> +	usb_anchor_urb(urb, &priv->anchored);
> +	if (usb_submit_urb(urb, GFP_ATOMIC))
> +		usb_unanchor_urb(urb);
>  }
>
>  static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
>  {
>  	struct rtl8187_priv *priv =3D dev->priv;
>  	struct urb *entry;
> +	int ret =3D 0;
>
>  	entry =3D usb_alloc_urb(0, GFP_KERNEL);
>  	if (!entry)
>  		return -ENOMEM;
> -	priv->b_tx_status.urb =3D entry;
>
>  	usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9)=
,
>  			  &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
>  			  rtl8187b_status_cb, dev);
>
> -	usb_submit_urb(entry, GFP_KERNEL);
> +	usb_anchor_urb(entry, &priv->anchored);
> +	ret =3D usb_submit_urb(entry, GFP_KERNEL);
> +	if (ret)
> +		usb_unanchor_urb(entry);
> +	usb_free_urb(entry);
>
> -	return 0;
> +	return ret;
>  }
>
>  static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
> @@ -841,6 +864,9 @@ static int rtl8187_start(struct ieee8021
>  		return ret;
>
>  	mutex_lock(&priv->conf_mutex);
> +
> +	init_usb_anchor(&priv->anchored);
> +
>  	if (priv->is_rtl8187b) {
>  		reg =3D RTL818X_RX_CONF_MGMT |
>  		      RTL818X_RX_CONF_DATA |
> @@ -936,12 +962,12 @@ static void rtl8187_stop(struct ieee8021
>
>  	while ((skb =3D skb_dequeue(&priv->rx_queue))) {
>  		info =3D (struct rtl8187_rx_info *)skb->cb;
> -		usb_kill_urb(info->urb);
>  		kfree_skb(skb);
>  	}
>  	while ((skb =3D skb_dequeue(&priv->b_tx_status.queue)))
>  		dev_kfree_skb_any(skb);
> -	usb_kill_urb(priv->b_tx_status.urb);
> +
> +	usb_kill_anchored_urbs(&priv->anchored);
>  	mutex_unlock(&priv->conf_mutex);
>  }

--
[]'s
Herton
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2008-12-09 19:06 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-09 16:33 [PATCH] rtl8187: Use usb anchor facilities to manage urbs Larry Finger
2008-12-09 19:06 ` Herton Ronaldo Krzesinski [this message]
2008-12-10  3:06   ` Larry Finger

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=200812091706.19994.herton@mandriva.com.br \
    --to=herton@mandriva.com.br \
    --cc=Larry.Finger@lwfinger.net \
    --cc=htl10@users.sourceforge.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.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).