[PATCH 53/70] USB: gadgetfs race fix

Greg KH <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
From: David Brownell <[email protected]>

This resolves a race in gadgetfs associated with changing device/ep0
when processing control requests.  The fix is to change that state
earlier, when the control response is issued, so there's no window
in which userspace could see the wrong state; and enlarge the scope
of the spinlock during the ep0 request completion handler.

Signed-off-by: David Brownell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/usb/gadget/inode.c |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index ea8e316..e5ce4f0 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -933,28 +933,24 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
 static void ep0_complete (struct usb_ep *ep, struct usb_request *req)
 {
 	struct dev_data		*dev = ep->driver_data;
+	unsigned long		flags;
 	int			free = 1;
 
 	/* for control OUT, data must still get to userspace */
+	spin_lock_irqsave(&dev->lock, flags);
 	if (!dev->setup_in) {
 		dev->setup_out_error = (req->status != 0);
 		if (!dev->setup_out_error)
 			free = 0;
 		dev->setup_out_ready = 1;
 		ep0_readable (dev);
-	} else {
-		unsigned long	flags;
-
-		spin_lock_irqsave(&dev->lock, flags);
-		if (dev->state == STATE_DEV_SETUP)
-			dev->state = STATE_DEV_CONNECTED;
-		spin_unlock_irqrestore(&dev->lock, flags);
 	}
 
 	/* clean up as appropriate */
 	if (free && req->buf != &dev->rbuf)
 		clean_req (ep, req);
 	req->complete = epio_complete;
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
@@ -1036,6 +1032,13 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 			spin_lock_irq (&dev->lock);
 			if (retval)
 				goto done;
+
+			if (dev->state != STATE_DEV_SETUP) {
+				retval = -ECANCELED;
+				goto done;
+			}
+			dev->state = STATE_DEV_CONNECTED;
+
 			if (dev->setup_out_error)
 				retval = -EIO;
 			else {
@@ -1187,6 +1190,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 		if (dev->setup_in) {
 			retval = setup_req (dev->gadget->ep0, dev->req, len);
 			if (retval == 0) {
+				dev->state = STATE_DEV_CONNECTED;
 				spin_unlock_irq (&dev->lock);
 				if (copy_from_user (dev->req->buf, buf, len))
 					retval = -EFAULT;
-- 
1.4.4.4


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.