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

Commit b8a3362f authored by Pavankumar Kondeti's avatar Pavankumar Kondeti Committed by Gerrit - the friendly Code Review server
Browse files

usb: gadget: u_ether: Fix memory corruption in TX path



When data aggregation is enabled, multiple skb buffers are copied
into a single USB request buffer.  When ever a USB request queue
is failed, make sure that req->length is reset to 0.  Otherwise
when the same request is used again, the stale length field is
used to access the request buffer.  This would lead to memory
corruption.

The xmit function keeps the partial request at the beginning of
the queue.  Always put the idle request at the back of the queue.

Change-Id: Idcd31e667b0bf261ab9a88f4a34464ccdf503e1b
Signed-off-by: default avatarPavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 68f7474a
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -573,6 +573,11 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
				switch (retval) {
				switch (retval) {
				default:
				default:
					DBG(dev, "tx queue err %d\n", retval);
					DBG(dev, "tx queue err %d\n", retval);
					new_req->length = 0;
					spin_lock(&dev->req_lock);
					list_add_tail(&new_req->list,
							&dev->tx_reqs);
					spin_unlock(&dev->req_lock);
					break;
					break;
				case 0:
				case 0:
					spin_lock(&dev->req_lock);
					spin_lock(&dev->req_lock);
@@ -582,7 +587,13 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
				}
				}
			} else {
			} else {
				spin_lock(&dev->req_lock);
				spin_lock(&dev->req_lock);
				list_add(&new_req->list, &dev->tx_reqs);
				/*
				 * Put the idle request at the back of the
				 * queue. The xmit function will put the
				 * unfinished request at the beginning of the
				 * queue.
				 */
				list_add_tail(&new_req->list, &dev->tx_reqs);
				spin_unlock(&dev->req_lock);
				spin_unlock(&dev->req_lock);
			}
			}
		} else {
		} else {
@@ -796,6 +807,8 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
	if (retval) {
	if (retval) {
		if (!multi_pkt_xfer)
		if (!multi_pkt_xfer)
			dev_kfree_skb_any(skb);
			dev_kfree_skb_any(skb);
		else
			req->length = 0;
drop:
drop:
		dev->net->stats.tx_dropped++;
		dev->net->stats.tx_dropped++;
multiframe:
multiframe: