summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2013-09-04 00:37:17 +0400
committerJohn W. Linville <linville@tuxdriver.com>2013-09-09 14:42:00 -0400
commit8a10da264663f97ad8b5c85343274ad903b32196 (patch)
tree39664637fe66be580f89b08299dfc01d2d822917
parentc4bff5d99da44b8aa2181cda6adf45479388d616 (diff)
rtl8187: fix use after free on failure path in rtl8187_init_urbs()
In case of __dev_alloc_skb() failure rtl8187_init_urbs() calls usb_free_urb(entry) where 'entry' can points to urb allocated at the previous iteration. That means refcnt will be decremented incorrectly and the urb can be used after memory deallocation. The patch fixes the issue and implements error handling of init_urbs in rtl8187_start(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 841fb9dfc9da..9a6edb0c014e 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -438,17 +438,16 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
skb_queue_tail(&priv->rx_queue, skb);
usb_anchor_urb(entry, &priv->anchored);
ret = usb_submit_urb(entry, GFP_KERNEL);
+ usb_put_urb(entry);
if (ret) {
skb_unlink(skb, &priv->rx_queue);
usb_unanchor_urb(entry);
goto err;
}
- usb_free_urb(entry);
}
return ret;
err:
- usb_free_urb(entry);
kfree_skb(skb);
usb_kill_anchored_urbs(&priv->anchored);
return ret;
@@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
(RETRY_COUNT << 8 /* short retry limit */) |
(RETRY_COUNT << 0 /* long retry limit */) |
(7 << 21 /* MAX TX DMA */));
- rtl8187_init_urbs(dev);
- rtl8187b_init_status_urb(dev);
+ ret = rtl8187_init_urbs(dev);
+ if (ret)
+ goto rtl8187_start_exit;
+ ret = rtl8187b_init_status_urb(dev);
+ if (ret)
+ usb_kill_anchored_urbs(&priv->anchored);
goto rtl8187_start_exit;
}
@@ -966,7 +969,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
- rtl8187_init_urbs(dev);
+ ret = rtl8187_init_urbs(dev);
+ if (ret)
+ goto rtl8187_start_exit;
reg = RTL818X_RX_CONF_ONLYERLPKT |
RTL818X_RX_CONF_RX_AUTORESETPHY |