aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl818x/rtl8187
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2013-09-03 16:37:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-09-09 14:42:00 -0400
commit8a10da264663f97ad8b5c85343274ad903b32196 (patch)
tree39664637fe66be580f89b08299dfc01d2d822917 /drivers/net/wireless/rtl818x/rtl8187
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>
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8187')
-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)
438 skb_queue_tail(&priv->rx_queue, skb); 438 skb_queue_tail(&priv->rx_queue, skb);
439 usb_anchor_urb(entry, &priv->anchored); 439 usb_anchor_urb(entry, &priv->anchored);
440 ret = usb_submit_urb(entry, GFP_KERNEL); 440 ret = usb_submit_urb(entry, GFP_KERNEL);
441 usb_put_urb(entry);
441 if (ret) { 442 if (ret) {
442 skb_unlink(skb, &priv->rx_queue); 443 skb_unlink(skb, &priv->rx_queue);
443 usb_unanchor_urb(entry); 444 usb_unanchor_urb(entry);
444 goto err; 445 goto err;
445 } 446 }
446 usb_free_urb(entry);
447 } 447 }
448 return ret; 448 return ret;
449 449
450err: 450err:
451 usb_free_urb(entry);
452 kfree_skb(skb); 451 kfree_skb(skb);
453 usb_kill_anchored_urbs(&priv->anchored); 452 usb_kill_anchored_urbs(&priv->anchored);
454 return ret; 453 return ret;
@@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
956 (RETRY_COUNT << 8 /* short retry limit */) | 955 (RETRY_COUNT << 8 /* short retry limit */) |
957 (RETRY_COUNT << 0 /* long retry limit */) | 956 (RETRY_COUNT << 0 /* long retry limit */) |
958 (7 << 21 /* MAX TX DMA */)); 957 (7 << 21 /* MAX TX DMA */));
959 rtl8187_init_urbs(dev); 958 ret = rtl8187_init_urbs(dev);
960 rtl8187b_init_status_urb(dev); 959 if (ret)
960 goto rtl8187_start_exit;
961 ret = rtl8187b_init_status_urb(dev);
962 if (ret)
963 usb_kill_anchored_urbs(&priv->anchored);
961 goto rtl8187_start_exit; 964 goto rtl8187_start_exit;
962 } 965 }
963 966
@@ -966,7 +969,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
966 rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); 969 rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
967 rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); 970 rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
968 971
969 rtl8187_init_urbs(dev); 972 ret = rtl8187_init_urbs(dev);
973 if (ret)
974 goto rtl8187_start_exit;
970 975
971 reg = RTL818X_RX_CONF_ONLYERLPKT | 976 reg = RTL818X_RX_CONF_ONLYERLPKT |
972 RTL818X_RX_CONF_RX_AUTORESETPHY | 977 RTL818X_RX_CONF_RX_AUTORESETPHY |