Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a10da26 authored by Alexey Khoroshilov's avatar Alexey Khoroshilov Committed by John W. Linville
Browse files

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: default avatarAlexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c4bff5d9
Loading
Loading
Loading
Loading
+10 −5
Original line number Original line Diff line number Diff line
@@ -438,17 +438,16 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
		skb_queue_tail(&priv->rx_queue, skb);
		skb_queue_tail(&priv->rx_queue, skb);
		usb_anchor_urb(entry, &priv->anchored);
		usb_anchor_urb(entry, &priv->anchored);
		ret = usb_submit_urb(entry, GFP_KERNEL);
		ret = usb_submit_urb(entry, GFP_KERNEL);
		usb_put_urb(entry);
		if (ret) {
		if (ret) {
			skb_unlink(skb, &priv->rx_queue);
			skb_unlink(skb, &priv->rx_queue);
			usb_unanchor_urb(entry);
			usb_unanchor_urb(entry);
			goto err;
			goto err;
		}
		}
		usb_free_urb(entry);
	}
	}
	return ret;
	return ret;


err:
err:
	usb_free_urb(entry);
	kfree_skb(skb);
	kfree_skb(skb);
	usb_kill_anchored_urbs(&priv->anchored);
	usb_kill_anchored_urbs(&priv->anchored);
	return ret;
	return ret;
@@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
				  (RETRY_COUNT << 8  /* short retry limit */) |
				  (RETRY_COUNT << 8  /* short retry limit */) |
				  (RETRY_COUNT << 0  /* long retry limit */) |
				  (RETRY_COUNT << 0  /* long retry limit */) |
				  (7 << 21 /* MAX TX DMA */));
				  (7 << 21 /* MAX TX DMA */));
		rtl8187_init_urbs(dev);
		ret = rtl8187_init_urbs(dev);
		rtl8187b_init_status_urb(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;
		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[0], ~0);
	rtl818x_iowrite32(priv, &priv->map->MAR[1], ~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 |
	reg = RTL818X_RX_CONF_ONLYERLPKT |
	      RTL818X_RX_CONF_RX_AUTORESETPHY |
	      RTL818X_RX_CONF_RX_AUTORESETPHY |