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

Commit a2c68edc authored by Hemant Kumar's avatar Hemant Kumar Committed by Sivasri Kumar Vanka
Browse files

usb: gadget: u_ether: Add NULL check for IN and OUT ep context



u_ether driver can used for a function driver which has only
IN endpoint for data transfer. This results into OUT ep context
as NULL and causes NULL pointer dereference. Hence check
both IN and OUT ep context before dereferencing the context pointer.

Change-Id: I77d909ce0954f3cc87fc2bd2be254854e4662d4a
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarSivasri Kumar Vanka <sivasri@codeaurora.org>
parent 9647c359
Loading
Loading
Loading
Loading
+81 −56
Original line number Diff line number Diff line
@@ -411,15 +411,20 @@ static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)

static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
{
	int	status;
	int	status = 0;

	spin_lock(&dev->req_lock);
	if (link->in_ep) {
		status = prealloc(&dev->tx_reqs, link->in_ep, n);
			if (status < 0)
				goto fail;
	}

	if (link->out_ep) {
		status = prealloc(&dev->rx_reqs, link->out_ep, n);
		if (status < 0)
			goto fail;
	}
	goto done;
fail:
	DBG(dev, "can't alloc requests\n");
@@ -902,18 +907,26 @@ static int eth_stop(struct net_device *net)
		 * their own pace; the network stack can handle old packets.
		 * For the moment we leave this here, since it works.
		 */
		if (link->in_ep) {
			in = link->in_ep->desc;
		out = link->out_ep->desc;
			usb_ep_disable(link->in_ep);
		usb_ep_disable(link->out_ep);
			if (netif_carrier_ok(net)) {
			DBG(dev, "host still using in/out endpoints\n");
				DBG(dev, "host still using in endpoints\n");
				link->in_ep->desc = in;
			link->out_ep->desc = out;
				usb_ep_enable(link->in_ep);
			}
		}

		if (link->out_ep) {
			out = link->out_ep->desc;
			usb_ep_disable(link->out_ep);
			if (netif_carrier_ok(net)) {
				DBG(dev, "host still using out endpoints\n");
				link->out_ep->desc = out;
				usb_ep_enable(link->out_ep);
			}
		}
	}
	spin_unlock_irqrestore(&dev->lock, flags);

	return 0;
@@ -1446,6 +1459,7 @@ struct net_device *gether_connect(struct gether *link)
	if (!dev)
		return ERR_PTR(-EINVAL);

	if (link->in_ep) {
		link->in_ep->driver_data = dev;
		result = usb_ep_enable(link->in_ep);
		if (result != 0) {
@@ -1453,7 +1467,9 @@ struct net_device *gether_connect(struct gether *link)
				link->in_ep->name, result);
			goto fail0;
		}
	}

	if (link->out_ep) {
		link->out_ep->driver_data = dev;
		result = usb_ep_enable(link->out_ep);
		if (result != 0) {
@@ -1461,6 +1477,7 @@ struct net_device *gether_connect(struct gether *link)
				link->out_ep->name, result);
			goto fail1;
		}
	}

	if (result == 0)
		result = alloc_requests(dev, link, qlen(dev->gadget,
@@ -1497,8 +1514,10 @@ struct net_device *gether_connect(struct gether *link)

	/* on error, disable any endpoints  */
	} else {
		if (link->out_ep)
			(void) usb_ep_disable(link->out_ep);
fail1:
		if (link->in_ep)
			(void) usb_ep_disable(link->in_ep);
	}
fail0:
@@ -1540,10 +1559,12 @@ void gether_disconnect(struct gether *link)
	 * of all pending i/o.  then free the request objects
	 * and forget about the endpoints.
	 */
	if (link->in_ep) {
		usb_ep_disable(link->in_ep);
		spin_lock(&dev->req_lock);
		while (!list_empty(&dev->tx_reqs)) {
		req = list_first_entry(&dev->tx_reqs, struct usb_request, list);
			req = list_first_entry(&dev->tx_reqs,
						struct usb_request, list);
			list_del(&req->list);

			spin_unlock(&dev->req_lock);
@@ -1554,11 +1575,14 @@ void gether_disconnect(struct gether *link)
		}
		spin_unlock(&dev->req_lock);
		link->in_ep->desc = NULL;
	}

	if (link->out_ep) {
		usb_ep_disable(link->out_ep);
		spin_lock(&dev->req_lock);
		while (!list_empty(&dev->rx_reqs)) {
		req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
			req = list_first_entry(&dev->rx_reqs,
						struct usb_request, list);
			list_del(&req->list);

			spin_unlock(&dev->req_lock);
@@ -1573,6 +1597,7 @@ void gether_disconnect(struct gether *link)
		spin_unlock(&dev->rx_frames.lock);

		link->out_ep->desc = NULL;
	}

	/* finish forgetting about this USB link episode */
	dev->header_len = 0;