mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org,
	Greg KH <greg@kroah.com>
Cc: Justin Forbes <jmforbes@linuxtx.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	"Theodore Ts'o" <tytso@mit.edu>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Dave Jones <davej@redhat.com>,
	Chuck Wolber <chuckw@quantumlinux.com>,
	Chris Wedgwood <reviews@ml.cw.f00f.org>,
	Michael Krufky <mkrufky@linuxtv.org>,
	Chuck Ebbert <cebbert@redhat.com>,
	Domenico Andreoli <cavokz@gmail.com>, Willy Tarreau <w@1wt.eu>,
	Rodrigo Rubira Branco <rbranco@la.checkpoint.com>,
	Jake Edge <jake@lwn.net>, Eugene Teo <eteo@redhat.com>,
	torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk, linville@tuxdriver.com,
	Larry.Finger@lwfinger.net, Christian Lamparter <chunkeey@web.de>
Subject: [patch 23/33] p54usb: rewriting rx/tx routines to make use of usb_anchors facilities
Date: Wed, 4 Feb 2009 10:35:01 -0800	[thread overview]
Message-ID: <20090204183501.GX13936@kroah.com> (raw)
In-Reply-To: <20090204183403.GA13936@kroah.com>

[-- Attachment #1: p54usb-rewriting-rx-tx-routines-to-make-use-of-usb_anchor-s-facilities.patch --]
[-- Type: text/plain, Size: 8235 bytes --]

2.6.28-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Christian Lamparter <chunkeey@web.de>

commit dd397dc9dddfa2149a1bbc9e52ac7d5630737cec upstream

Alan Stern found several flaws in p54usb's implementation and annotated:
"usb_kill_urb() and similar routines do not expect an URB's completion
routine to deallocate it.  This is almost obvious -- if the URB is deallocated
before the completion routine returns then there's no way for usb_kill_urb
to detect when the URB actually is complete."

This patch addresses all known limitations in the old implementation and fixes
khub's "use-after-freed" hang, when SLUB debug's poisoning option is enabled.

Signed-off-by: Christian Lamparter <chunkeey@web.de>
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/net/wireless/p54/p54usb.c |  143 +++++++++++++++++++++++---------------
 drivers/net/wireless/p54/p54usb.h |    1 
 2 files changed, 89 insertions(+), 55 deletions(-)

--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -85,13 +85,13 @@ static void p54u_rx_cb(struct urb *urb)
 	struct ieee80211_hw *dev = info->dev;
 	struct p54u_priv *priv = dev->priv;
 
+	skb_unlink(skb, &priv->rx_queue);
+
 	if (unlikely(urb->status)) {
-		info->urb = NULL;
-		usb_free_urb(urb);
+		dev_kfree_skb_irq(skb);
 		return;
 	}
 
-	skb_unlink(skb, &priv->rx_queue);
 	skb_put(skb, urb->actual_length);
 
 	if (priv->hw_type == P54U_NET2280)
@@ -104,7 +104,6 @@ static void p54u_rx_cb(struct urb *urb)
 	if (p54_rx(dev, skb)) {
 		skb = dev_alloc_skb(priv->common.rx_mtu + 32);
 		if (unlikely(!skb)) {
-			usb_free_urb(urb);
 			/* TODO check rx queue length and refill *somewhere* */
 			return;
 		}
@@ -114,7 +113,6 @@ static void p54u_rx_cb(struct urb *urb)
 		info->dev = dev;
 		urb->transfer_buffer = skb_tail_pointer(skb);
 		urb->context = skb;
-		skb_queue_tail(&priv->rx_queue, skb);
 	} else {
 		if (priv->hw_type == P54U_NET2280)
 			skb_push(skb, priv->common.tx_hdr_len);
@@ -129,22 +127,23 @@ static void p54u_rx_cb(struct urb *urb)
 			WARN_ON(1);
 			urb->transfer_buffer = skb_tail_pointer(skb);
 		}
-
-		skb_queue_tail(&priv->rx_queue, skb);
 	}
 
-	usb_submit_urb(urb, GFP_ATOMIC);
+	usb_anchor_urb(urb, &priv->submitted);
+	if (usb_submit_urb(urb, GFP_ATOMIC)) {
+		usb_unanchor_urb(urb);
+		dev_kfree_skb_irq(skb);
+	} else
+		skb_queue_tail(&priv->rx_queue, skb);
 }
 
-static void p54u_tx_cb(struct urb *urb)
-{
-	usb_free_urb(urb);
-}
+static void p54u_tx_cb(struct urb *urb) { }
 
-static void p54u_tx_free_cb(struct urb *urb)
+static void p54u_free_urbs(struct ieee80211_hw *dev)
 {
-	kfree(urb->transfer_buffer);
-	usb_free_urb(urb);
+	struct p54u_priv *priv = dev->priv;
+
+	usb_kill_anchored_urbs(&priv->submitted);
 }
 
 static int p54u_init_urbs(struct ieee80211_hw *dev)
@@ -153,15 +152,18 @@ static int p54u_init_urbs(struct ieee802
 	struct urb *entry;
 	struct sk_buff *skb;
 	struct p54u_rx_info *info;
+	int ret = 0;
 
 	while (skb_queue_len(&priv->rx_queue) < 32) {
 		skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
-		if (!skb)
-			break;
+		if (!skb) {
+			ret = -ENOMEM;
+			goto err;
+		}
 		entry = usb_alloc_urb(0, GFP_KERNEL);
 		if (!entry) {
-			kfree_skb(skb);
-			break;
+			ret = -ENOMEM;
+			goto err;
 		}
 		usb_fill_bulk_urb(entry, priv->udev,
 				  usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
@@ -171,26 +173,25 @@ static int p54u_init_urbs(struct ieee802
 		info->urb = entry;
 		info->dev = dev;
 		skb_queue_tail(&priv->rx_queue, skb);
-		usb_submit_urb(entry, GFP_KERNEL);
+
+		usb_anchor_urb(entry, &priv->submitted);
+		ret = usb_submit_urb(entry, GFP_KERNEL);
+		if (ret) {
+			skb_unlink(skb, &priv->rx_queue);
+			usb_unanchor_urb(entry);
+			goto err;
+		}
+		usb_free_urb(entry);
+		entry = NULL;
 	}
 
 	return 0;
-}
-
-static void p54u_free_urbs(struct ieee80211_hw *dev)
-{
-	struct p54u_priv *priv = dev->priv;
-	struct p54u_rx_info *info;
-	struct sk_buff *skb;
 
-	while ((skb = skb_dequeue(&priv->rx_queue))) {
-		info = (struct p54u_rx_info *) skb->cb;
-		if (!info->urb)
-			continue;
-
-		usb_kill_urb(info->urb);
-		kfree_skb(skb);
-	}
+err:
+	usb_free_urb(entry);
+	kfree_skb(skb);
+	p54u_free_urbs(dev);
+	return ret;
 }
 
 static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
@@ -210,16 +211,29 @@ static void p54u_tx_3887(struct ieee8021
 	}
 
 	usb_fill_bulk_urb(addr_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
-		sizeof(data->req_id), p54u_tx_cb, dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  &data->req_id, sizeof(data->req_id), p54u_tx_cb,
+			  dev);
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  data, len, p54u_tx_cb, dev);
 	addr_urb->transfer_flags |= URB_ZERO_PACKET;
-	data_urb->transfer_flags |= URB_ZERO_PACKET;
+	data_urb->transfer_flags |= URB_ZERO_PACKET |
+				    (free_on_tx ? URB_FREE_BUFFER : 0);
 
-	usb_submit_urb(addr_urb, GFP_ATOMIC);
-	usb_submit_urb(data_urb, GFP_ATOMIC);
+	usb_anchor_urb(addr_urb, &priv->submitted);
+	if (usb_submit_urb(addr_urb, GFP_ATOMIC)) {
+		usb_unanchor_urb(addr_urb);
+		goto out;
+	}
+
+	usb_anchor_urb(data_urb, &priv->submitted);
+	if (usb_submit_urb(data_urb, GFP_ATOMIC))
+		usb_unanchor_urb(data_urb);
+
+out:
+	usb_free_urb(addr_urb);
+	usb_free_urb(data_urb);
 }
 
 static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
@@ -251,12 +265,16 @@ static void p54u_tx_lm87(struct ieee8021
 	hdr->device_addr = data->req_id;
 
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
-		len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
-		dev);
-	data_urb->transfer_flags |= URB_ZERO_PACKET;
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
+			  len + sizeof(*hdr), p54u_tx_cb, dev);
+	data_urb->transfer_flags |= URB_ZERO_PACKET |
+				    (free_on_tx ? URB_FREE_BUFFER : 0);
+
+	usb_anchor_urb(data_urb, &priv->submitted);
+	if (usb_submit_urb(data_urb, GFP_ATOMIC))
+		usb_unanchor_urb(data_urb);
 
-	usb_submit_urb(data_urb, GFP_ATOMIC);
+	usb_free_urb(data_urb);
 }
 
 static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
@@ -295,16 +313,30 @@ static void p54u_tx_net2280(struct ieee8
 	hdr->len = cpu_to_le16(len);
 
 	usb_fill_bulk_urb(int_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
-		p54u_tx_free_cb, dev);
-	int_urb->transfer_flags |= URB_ZERO_PACKET;
-	usb_submit_urb(int_urb, GFP_ATOMIC);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV),
+			  reg, sizeof(*reg), p54u_tx_cb, dev);
+	int_urb->transfer_flags |= URB_ZERO_PACKET | URB_FREE_BUFFER;
+	usb_anchor_urb(int_urb, &priv->submitted);
+	if (usb_submit_urb(int_urb, GFP_ATOMIC)) {
+		usb_unanchor_urb(int_urb);
+		goto out;
+	}
 
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
-	data_urb->transfer_flags |= URB_ZERO_PACKET;
-	usb_submit_urb(data_urb, GFP_ATOMIC);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
+			  len + sizeof(*hdr), p54u_tx_cb, dev);
+	data_urb->transfer_flags |= URB_ZERO_PACKET |
+				    (free_on_tx ? URB_FREE_BUFFER : 0);
+
+	usb_anchor_urb(int_urb, &priv->submitted);
+	if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
+		usb_unanchor_urb(data_urb);
+		goto out;
+	}
+
+out:
+	usb_free_urb(int_urb);
+	usb_free_urb(data_urb);
 }
 
 static int p54u_write(struct p54u_priv *priv,
@@ -805,6 +837,7 @@ static int __devinit p54u_probe(struct u
 	SET_IEEE80211_DEV(dev, &intf->dev);
 	usb_set_intfdata(intf, dev);
 	priv->udev = udev;
+	init_usb_anchor(&priv->submitted);
 
 	usb_get_dev(udev);
 
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -133,6 +133,7 @@ struct p54u_priv {
 
 	spinlock_t lock;
 	struct sk_buff_head rx_queue;
+	struct usb_anchor submitted;
 };
 
 #endif /* P54USB_H */


  parent reply	other threads:[~2009-02-04 18:45 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20090204182823.831027530@mini.kroah.org>
2009-02-04 18:34 ` [patch 00/33] 2.6.28-stable review Greg KH
2009-02-04 18:34   ` [patch 01/33] Manually revert "mlock: downgrade mmap sem while populating mlocked regions" Greg KH
2009-02-04 18:34   ` [patch 02/33] xen: make sysfs files behave as their names suggest Greg KH
2009-02-04 18:34   ` [patch 03/33] sata_mv: fix 8-port timeouts on 508x/6081 chips Greg KH
2009-02-04 18:34   ` [patch 04/33] m68knommu: set NO_DMA Greg KH
2009-02-04 18:34   ` [patch 05/33] PCI/MSI: bugfix/utilize for msi_capability_init() Greg KH
2009-02-04 18:34   ` [patch 06/33] x86: use early clobbers in usercopy*.c Greg KH
2009-02-04 18:34   ` [patch 07/33] cifs: make sure we allocate enough storage for socket address Greg KH
2009-02-04 18:34   ` [patch 08/33] netfilter: ctnetlink: fix scheduling while atomic Greg KH
2009-02-04 18:34   ` [patch 09/33] orinoco: move kmalloc(..., GFP_KERNEL) outside spinlock in orinoco_ioctl_set_genie Greg KH
2009-02-04 18:34   ` [patch 10/33] fbdev/atyfb: Fix DSP config on some PowerMacs & PowerBooks Greg KH
2009-02-04 18:34   ` [patch 11/33] kmalloc: return NULL instead of link failure Greg KH
2009-02-04 18:34   ` [patch 12/33] sata_nv: rename nv_nf2_hardreset() Greg KH
2009-02-04 18:34   ` [patch 13/33] sata_nv: fix MCP5x reset Greg KH
2009-02-04 18:34   ` [patch 14/33] sata_nv: ck804 has borked hardreset too Greg KH
2009-02-04 18:34   ` [patch 15/33] Fix memory corruption in console selection Greg KH
2009-02-04 18:34   ` [patch 16/33] Add enable_ms to jsm driver Greg KH
2009-02-04 18:34   ` [patch 17/33] Input: atkbd - Samsung NC10 key repeat fix Greg KH
2009-02-04 18:34   ` [patch 18/33] nfsd: only set file_lock.fl_lmops in nfsd4_lockt if a stateowner is found Greg KH
2009-02-04 18:34   ` [patch 19/33] nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT Greg KH
2009-02-04 18:34   ` [patch 20/33] iwlwifi: fix rs_get_rate WARN_ON() Greg KH
2009-02-04 18:34   ` [patch 21/33] p54: fix lm87 checksum endianness Greg KH
2009-02-04 18:34   ` [patch 22/33] p54: fix p54_read_eeprom to cope with tx_hdr_len Greg KH
2009-02-04 18:35   ` Greg KH [this message]
2009-02-04 18:35   ` [patch 24/33] minstrel: fix warning if lowest supported rate index is not 0 Greg KH
2009-02-04 18:35   ` [patch 25/33] PCI: irq and pci_ids patch for Intel Tigerpoint DeviceIDs Greg KH
2009-02-04 18:35   ` [patch 26/33] cpuidle: Add decaying history logic to menu idle predictor Greg KH
2009-02-04 18:35   ` [patch 27/33] ACPI: Avoid array address overflow when _CST MWAIT hint bits are set Greg KH
2009-02-04 18:35   ` [patch 28/33] video: always update the brightness when poking "brightness" Greg KH
2009-02-04 18:35   ` [patch 29/33] Newly inserted battery might differ from one just removed, so Greg KH
2009-02-04 18:35   ` [patch 30/33] ACPI: Do not modify SCI_EN directly Greg KH
2009-02-04 18:35   ` [patch 31/33] dlm: initialize file_lock struct in GETLK before copying conflicting lock Greg KH
2009-02-04 18:35   ` [patch 32/33] sata_mv: Fix chip type for Hightpoint RocketRaid 1740/1742 Greg KH
2009-02-04 18:35   ` [patch 33/33] ACPICA: Allow multiple backslash prefix in namepaths Greg KH

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=20090204183501.GX13936@kroah.com \
    --to=gregkh@suse.de \
    --cc=Larry.Finger@lwfinger.net \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cavokz@gmail.com \
    --cc=cebbert@redhat.com \
    --cc=chuckw@quantumlinux.com \
    --cc=chunkeey@web.de \
    --cc=davej@redhat.com \
    --cc=eteo@redhat.com \
    --cc=greg@kroah.com \
    --cc=jake@lwn.net \
    --cc=jmforbes@linuxtx.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=mkrufky@linuxtv.org \
    --cc=rbranco@la.checkpoint.com \
    --cc=rdunlap@xenotime.net \
    --cc=reviews@ml.cw.f00f.org \
    --cc=stable@kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=tytso@mit.edu \
    --cc=w@1wt.eu \
    --cc=zwane@arm.linux.org.uk \
    /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

Powered by JetHome