From 15d49a10511d64362bdbb597c44a3337e8f54ce7 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Wed, 25 Feb 2015 10:56:20 +0530 Subject: [PATCH] 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: Vijayavardhan Vennapusa Signed-off-by: Azhar Shaikh --- drivers/usb/gadget/composite.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index bb59a2de8f1f..acb925be0482 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -367,9 +367,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 : ""); @@ -388,11 +386,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; } @@ -400,10 +394,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, @@ -416,6 +412,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_GPL(usb_func_wakeup); @@ -2250,7 +2247,8 @@ void composite_resume(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; u16 maxpower; - int ret; + int ret; + unsigned long flags; /* REVISIT: should we have config level * suspend/resume callbacks? @@ -2259,6 +2257,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); @@ -2286,6 +2285,7 @@ void composite_resume(struct usb_gadget *gadget) maxpower : CONFIG_USB_GADGET_VBUS_DRAW); } + spin_unlock_irqrestore(&cdev->lock, flags); cdev->suspended = 0; }