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

Commit 7d4a6cb4 authored by Rajkumar Raghupathy's avatar Rajkumar Raghupathy Committed by Gerrit - the friendly Code Review server
Browse files

u_ether: Handle memory allocation failure case on tx path



With multipacket feature enabled, if the memory allocation for
tx request buffer fails, accessing the req->buf leads to null
pointer dereference.

Hence, handle memory alloction failure case and return -ENOMEM.

Change-Id: Ic5faac8ea7eb056755b03007c48ff085f10afa20
Signed-off-by: default avatarRajkumar Raghupathy <raghup@codeaurora.org>
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 2e385144
Loading
Loading
Loading
Loading
+23 −4
Original line number Diff line number Diff line
@@ -613,7 +613,7 @@ static inline int is_promisc(u16 cdc_filter)
	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
}

static void alloc_tx_buffer(struct eth_dev *dev)
static int alloc_tx_buffer(struct eth_dev *dev)
{
	struct list_head	*act;
	struct usb_request	*req;
@@ -630,7 +630,21 @@ static void alloc_tx_buffer(struct eth_dev *dev)
		if (!req->buf)
			req->buf = kmalloc(dev->tx_req_bufsize,
						GFP_ATOMIC);

		if (!req->buf)
			goto free_buf;
	}
	return 0;

free_buf:
	/* tx_req_bufsize = 0 retries mem alloc on next eth_start_xmit */
	dev->tx_req_bufsize = 0;
	list_for_each(act, &dev->tx_reqs) {
		req = container_of(act, struct usb_request, list);
		kfree(req->buf);
		req->buf = NULL;
	}
	return -ENOMEM;
}

static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
@@ -662,8 +676,11 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
	}

	/* Allocate memory for tx_reqs to support multi packet transfer */
	if (multi_pkt_xfer && !dev->tx_req_bufsize)
		alloc_tx_buffer(dev);
	if (multi_pkt_xfer && !dev->tx_req_bufsize) {
		retval = alloc_tx_buffer(dev);
		if (retval < 0)
			return -ENOMEM;
	}

	/* apply outgoing CDC or RNDIS filters */
	if (skb && !is_promisc(cdc_filter)) {
@@ -1534,8 +1551,10 @@ void gether_disconnect(struct gether *link)
			list_del(&req->list);

			spin_unlock(&dev->req_lock);
			if (link->multi_pkt_xfer)
			if (link->multi_pkt_xfer) {
				kfree(req->buf);
				req->buf = NULL;
			}
			usb_ep_free_request(link->in_ep, req);
			spin_lock(&dev->req_lock);
		}