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

Commit d251f8b2 authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa Committed by Ajay Agarwal
Browse files

USB: gadget: rndis: Flush rx_work before free_net_dev in cleanup



gether_cleanup() gets called during unbind() and as part of
cleanup, driver flushes work pending and freeing net device. But
it is not flushing pending rx_work. This could cause NULL
pointer access later. Hence flush rx_work before freeing net
device during cleanup to fix the issue.

Also get rndis value from global pointer __rndis under spin lock
in rndis_command_complete/rndis_response_complete callbacks.

Change-Id: Ic2813cf0fff670c12e532b915f6ef2c71df17ddc
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 341fa079
Loading
Loading
Loading
Loading
+8 −4
Original line number Original line Diff line number Diff line
@@ -425,17 +425,19 @@ static void rndis_response_available(void *_rndis)


static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
{
{
	struct f_rndis			*rndis = __rndis;
	struct f_rndis			*rndis;
	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
	struct usb_composite_dev	*cdev;
	int				status = req->status;
	int				status = req->status;
	struct usb_ep *notify_ep;
	struct usb_ep *notify_ep;


	spin_lock(&_rndis_lock);
	spin_lock(&_rndis_lock);
	rndis = __rndis;
	if (!rndis || !rndis->notify) {
	if (!rndis || !rndis->notify) {
		spin_unlock(&_rndis_lock);
		spin_unlock(&_rndis_lock);
		return;
		return;
	}
	}


	cdev = rndis->port.func.config->cdev;
	/* after TX:
	/* after TX:
	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
@@ -481,17 +483,19 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)


static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
{
{
	struct f_rndis			*rndis = __rndis;
	struct f_rndis			*rndis;
	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
	struct usb_composite_dev	*cdev;
	int				status;
	int				status;
	rndis_init_msg_type		*buf;
	rndis_init_msg_type		*buf;


	spin_lock(&_rndis_lock);
	spin_lock(&_rndis_lock);
	rndis = __rndis;
	if (!rndis || !rndis->notify) {
	if (!rndis || !rndis->notify) {
		spin_unlock(&_rndis_lock);
		spin_unlock(&_rndis_lock);
		return;
		return;
	}
	}


	cdev = rndis->port.func.config->cdev;
	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
//	spin_lock(&dev->lock);
//	spin_lock(&dev->lock);
	status = rndis_msg_parser(rndis->params, (u8 *) req->buf);
	status = rndis_msg_parser(rndis->params, (u8 *) req->buf);
+1 −0
Original line number Original line Diff line number Diff line
@@ -1533,6 +1533,7 @@ void gether_cleanup(struct eth_dev *dev)
	uether_debugfs_exit(dev);
	uether_debugfs_exit(dev);
	unregister_netdev(dev->net);
	unregister_netdev(dev->net);
	flush_work(&dev->work);
	flush_work(&dev->work);
	cancel_work_sync(&dev->rx_work);
	free_netdev(dev->net);
	free_netdev(dev->net);
}
}
EXPORT_SYMBOL_GPL(gether_cleanup);
EXPORT_SYMBOL_GPL(gether_cleanup);