From: Jack Pham Date: Wed, 19 Feb 2014 06:16:19 +0000 (-0800) Subject: usb: gadget: android: Save/restore ep0 completion function X-Git-Tag: firefly_0821_release~4090^2~88 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ea262b409baefe776613660d6b7fdf029f5c96be;p=firefly-linux-kernel-4.4.55.git usb: gadget: android: Save/restore ep0 completion function The android_setup() function currently gives the f_accessory setup function first opportunity to handle control requests in order to support Android Open Accessory (AOA) hosts. That function makes use of cdev->req and overrides its completion function, but not in all cases. Thus, if a later request uses the same request pointer but doesn't (re)set req->complete it could result in the wrong completion function being called and causing invalid memory access. One way to fix this would be to explicitly set req->complete in all cases but that might require auditing all function drivers that have ep0 handling. Instead, note that the composite device had already initially set cdev->req->complete and simply cache and restore that pointer at the start of android_setup(). Change-Id: I33bcd17bd20687a349d537d1013b52a2afef6996 Signed-off-by: Jack Pham --- diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index 04cbeb134814..83b1240d9b19 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -90,6 +90,9 @@ struct android_dev { struct usb_composite_dev *cdev; struct device *dev; + void (*setup_complete)(struct usb_ep *ep, + struct usb_request *req); + bool enabled; int disable_depth; struct mutex mutex; @@ -1312,6 +1315,9 @@ static int android_bind(struct usb_composite_dev *cdev) struct usb_gadget *gadget = cdev->gadget; int id, ret; + /* Save the default handler */ + dev->setup_complete = cdev->req->complete; + /* * Start disconnected. Userspace will connect the gadget once * it is done configuring the functions. @@ -1378,6 +1384,7 @@ android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c) req->zero = 0; req->length = 0; + req->complete = dev->setup_complete; gadget->ep0->driver_data = cdev; list_for_each_entry(f, &dev->enabled_functions, enabled_list) {