Skip to content

Commit c1db52b

Browse files
lwfingerlinvjw
authored andcommitted
rtl8187: Use usb anchor facilities to manage urbs
When SLUB debugging is enabled in the kernel, and the boot command includes the option "slub_debug=P", 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, the 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=12185). Signed-off-by: Larry Finger <[email protected]> Tested-by: Hin-Tak Leung <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent 388cdf3 commit c1db52b

File tree

2 files changed

+52
-25
lines changed

2 files changed

+52
-25
lines changed

drivers/net/wireless/rtl818x/rtl8187.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct rtl8187_priv {
9999
struct ieee80211_supported_band band;
100100
struct usb_device *udev;
101101
u32 rx_conf;
102+
struct usb_anchor anchored;
102103
u16 txpwr_base;
103104
u8 asic_rev;
104105
u8 is_rtl8187b;
@@ -115,7 +116,6 @@ struct rtl8187_priv {
115116
u8 aifsn[4];
116117
struct {
117118
__le64 buf;
118-
struct urb *urb;
119119
struct sk_buff_head queue;
120120
} b_tx_status;
121121
};

drivers/net/wireless/rtl818x/rtl8187_dev.c

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
9999
static void rtl8187_iowrite_async_cb(struct urb *urb)
100100
{
101101
kfree(urb->context);
102-
usb_free_urb(urb);
103102
}
104103

105104
static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
@@ -136,11 +135,13 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
136135
usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
137136
(unsigned char *)dr, buf, len,
138137
rtl8187_iowrite_async_cb, buf);
138+
usb_anchor_urb(urb, &priv->anchored);
139139
rc = usb_submit_urb(urb, GFP_ATOMIC);
140140
if (rc < 0) {
141141
kfree(buf);
142-
usb_free_urb(urb);
142+
usb_unanchor_urb(urb);
143143
}
144+
usb_free_urb(urb);
144145
}
145146

146147
static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
@@ -172,7 +173,6 @@ static void rtl8187_tx_cb(struct urb *urb)
172173
struct ieee80211_hw *hw = info->rate_driver_data[0];
173174
struct rtl8187_priv *priv = hw->priv;
174175

175-
usb_free_urb(info->rate_driver_data[1]);
176176
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
177177
sizeof(struct rtl8187_tx_hdr));
178178
ieee80211_tx_info_clear_status(info);
@@ -273,11 +273,13 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
273273

274274
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
275275
buf, skb->len, rtl8187_tx_cb, skb);
276+
usb_anchor_urb(urb, &priv->anchored);
276277
rc = usb_submit_urb(urb, GFP_ATOMIC);
277278
if (rc < 0) {
278-
usb_free_urb(urb);
279+
usb_unanchor_urb(urb);
279280
kfree_skb(skb);
280281
}
282+
usb_free_urb(urb);
281283

282284
return 0;
283285
}
@@ -301,14 +303,13 @@ static void rtl8187_rx_cb(struct urb *urb)
301303
return;
302304
}
303305
spin_unlock(&priv->rx_queue.lock);
306+
skb_put(skb, urb->actual_length);
304307

305308
if (unlikely(urb->status)) {
306-
usb_free_urb(urb);
307309
dev_kfree_skb_irq(skb);
308310
return;
309311
}
310312

311-
skb_put(skb, urb->actual_length);
312313
if (!priv->is_rtl8187b) {
313314
struct rtl8187_rx_hdr *hdr =
314315
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
@@ -361,7 +362,6 @@ static void rtl8187_rx_cb(struct urb *urb)
361362

362363
skb = dev_alloc_skb(RTL8187_MAX_RX);
363364
if (unlikely(!skb)) {
364-
usb_free_urb(urb);
365365
/* TODO check rx queue length and refill *somewhere* */
366366
return;
367367
}
@@ -373,24 +373,32 @@ static void rtl8187_rx_cb(struct urb *urb)
373373
urb->context = skb;
374374
skb_queue_tail(&priv->rx_queue, skb);
375375

376-
usb_submit_urb(urb, GFP_ATOMIC);
376+
usb_anchor_urb(urb, &priv->anchored);
377+
if (usb_submit_urb(urb, GFP_ATOMIC)) {
378+
usb_unanchor_urb(urb);
379+
skb_unlink(skb, &priv->rx_queue);
380+
dev_kfree_skb_irq(skb);
381+
}
377382
}
378383

379384
static int rtl8187_init_urbs(struct ieee80211_hw *dev)
380385
{
381386
struct rtl8187_priv *priv = dev->priv;
382-
struct urb *entry;
387+
struct urb *entry = NULL;
383388
struct sk_buff *skb;
384389
struct rtl8187_rx_info *info;
390+
int ret = 0;
385391

386392
while (skb_queue_len(&priv->rx_queue) < 8) {
387393
skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
388-
if (!skb)
389-
break;
394+
if (!skb) {
395+
ret = -ENOMEM;
396+
goto err;
397+
}
390398
entry = usb_alloc_urb(0, GFP_KERNEL);
391399
if (!entry) {
392-
kfree_skb(skb);
393-
break;
400+
ret = -ENOMEM;
401+
goto err;
394402
}
395403
usb_fill_bulk_urb(entry, priv->udev,
396404
usb_rcvbulkpipe(priv->udev,
@@ -401,10 +409,22 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
401409
info->urb = entry;
402410
info->dev = dev;
403411
skb_queue_tail(&priv->rx_queue, skb);
404-
usb_submit_urb(entry, GFP_KERNEL);
412+
usb_anchor_urb(entry, &priv->anchored);
413+
ret = usb_submit_urb(entry, GFP_KERNEL);
414+
if (ret) {
415+
skb_unlink(skb, &priv->rx_queue);
416+
usb_unanchor_urb(entry);
417+
goto err;
418+
}
419+
usb_free_urb(entry);
405420
}
421+
return ret;
406422

407-
return 0;
423+
err:
424+
usb_free_urb(entry);
425+
kfree_skb(skb);
426+
usb_kill_anchored_urbs(&priv->anchored);
427+
return ret;
408428
}
409429

410430
static void rtl8187b_status_cb(struct urb *urb)
@@ -414,10 +434,8 @@ static void rtl8187b_status_cb(struct urb *urb)
414434
u64 val;
415435
unsigned int cmd_type;
416436

417-
if (unlikely(urb->status)) {
418-
usb_free_urb(urb);
437+
if (unlikely(urb->status))
419438
return;
420-
}
421439

422440
/*
423441
* Read from status buffer:
@@ -488,26 +506,32 @@ static void rtl8187b_status_cb(struct urb *urb)
488506
spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
489507
}
490508

491-
usb_submit_urb(urb, GFP_ATOMIC);
509+
usb_anchor_urb(urb, &priv->anchored);
510+
if (usb_submit_urb(urb, GFP_ATOMIC))
511+
usb_unanchor_urb(urb);
492512
}
493513

494514
static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
495515
{
496516
struct rtl8187_priv *priv = dev->priv;
497517
struct urb *entry;
518+
int ret = 0;
498519

499520
entry = usb_alloc_urb(0, GFP_KERNEL);
500521
if (!entry)
501522
return -ENOMEM;
502-
priv->b_tx_status.urb = entry;
503523

504524
usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
505525
&priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
506526
rtl8187b_status_cb, dev);
507527

508-
usb_submit_urb(entry, GFP_KERNEL);
528+
usb_anchor_urb(entry, &priv->anchored);
529+
ret = usb_submit_urb(entry, GFP_KERNEL);
530+
if (ret)
531+
usb_unanchor_urb(entry);
532+
usb_free_urb(entry);
509533

510-
return 0;
534+
return ret;
511535
}
512536

513537
static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
@@ -841,6 +865,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
841865
return ret;
842866

843867
mutex_lock(&priv->conf_mutex);
868+
869+
init_usb_anchor(&priv->anchored);
870+
844871
if (priv->is_rtl8187b) {
845872
reg = RTL818X_RX_CONF_MGMT |
846873
RTL818X_RX_CONF_DATA |
@@ -936,12 +963,12 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
936963

937964
while ((skb = skb_dequeue(&priv->rx_queue))) {
938965
info = (struct rtl8187_rx_info *)skb->cb;
939-
usb_kill_urb(info->urb);
940966
kfree_skb(skb);
941967
}
942968
while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
943969
dev_kfree_skb_any(skb);
944-
usb_kill_urb(priv->b_tx_status.urb);
970+
971+
usb_kill_anchored_urbs(&priv->anchored);
945972
mutex_unlock(&priv->conf_mutex);
946973
}
947974

0 commit comments

Comments
 (0)