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

Commit 73beaeae authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa Committed by Mayank Rana
Browse files

USB: composite: Hold spinlock before calling usb_func_wakeup_int() API



There is a chance that composite_resume might race with android_disable
if composition switch happens and at the same time, reset interrupt is
triggered. In this case, it could lead to accessing invalid address as
composite_resume() not calling usb_func_wakeup_int() without holding
spinlock. Hence modfiy usb_func_wakeup_int() such that caller of this
function should call it with spinlock holding to fix the issue.

CRs-Fixed: 799332
Change-Id: I97ef374923504977ac8fc32954dd7de834a01041
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 2f2ed9a8
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -422,9 +422,7 @@ EXPORT_SYMBOL_GPL(usb_interface_id);
static int usb_func_wakeup_int(struct usb_function *func)
{
	int ret;
	unsigned long flags;
	struct usb_gadget *gadget;
	struct usb_composite_dev *cdev;

	pr_debug("%s - %s function wakeup\n",
		__func__, func->name ? func->name : "");
@@ -443,10 +441,7 @@ static int usb_func_wakeup_int(struct usb_function *func)
		return -ENOTSUPP;
	}

	cdev = get_gadget_data(gadget);
	spin_lock_irqsave(&cdev->lock, flags);
	ret = usb_gadget_func_wakeup(gadget, func->intf_id);
	spin_unlock_irqrestore(&cdev->lock, flags);

	return ret;
}
@@ -454,10 +449,12 @@ static int usb_func_wakeup_int(struct usb_function *func)
int usb_func_wakeup(struct usb_function *func)
{
	int ret;
	unsigned long flags;

	pr_debug("%s function wakeup\n",
		func->name ? func->name : "");

	spin_lock_irqsave(&func->config->cdev->lock, flags);
	ret = usb_func_wakeup_int(func);
	if (ret == -EAGAIN) {
		DBG(func->config->cdev,
@@ -470,6 +467,7 @@ int usb_func_wakeup(struct usb_function *func)
			func->name ? func->name : "", ret);
	}

	spin_unlock_irqrestore(&func->config->cdev->lock, flags);
	return ret;
}
EXPORT_SYMBOL(usb_func_wakeup);
@@ -2373,6 +2371,7 @@ void composite_resume(struct usb_gadget *gadget)
	struct usb_function		*f;
	u16				maxpower;
	int				ret;
	unsigned long			flags;

	/* REVISIT:  should we have config level
	 * suspend/resume callbacks?
@@ -2381,6 +2380,7 @@ void composite_resume(struct usb_gadget *gadget)
	if (cdev->driver->resume)
		cdev->driver->resume(cdev);

	spin_lock_irqsave(&cdev->lock, flags);
	if (cdev->config) {
		list_for_each_entry(f, &cdev->config->functions, list) {
			ret = usb_func_wakeup_int(f);
@@ -2408,6 +2408,7 @@ void composite_resume(struct usb_gadget *gadget)
			maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
	}

	spin_unlock_irqrestore(&cdev->lock, flags);
	cdev->suspended = 0;
}