ANDROID: usb: gadget: fix NULL pointer dereference in android_setup

This is a possibility in android_setup when using cdev leading
to a NULL pointer dereference in spin_lock_irqsave. Using the
spinlock of gadget item to prevent the condition.

Bug: 189800931
Signed-off-by: Ray Chi <raychi@google.com>
Change-Id: Idc4cbcaed7dc6e1e35e8a63de84c1415fb83ef5e
This commit is contained in:
Ray Chi 2021-07-08 17:15:26 +08:00 committed by Greg Kroah-Hartman
parent 07f65598af
commit dd139186ef

View File

@ -1534,18 +1534,28 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
static int android_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *c)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_composite_dev *cdev;
unsigned long flags;
struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
struct gadget_info *gi;
int value = -EOPNOTSUPP;
struct usb_function_instance *fi;
spin_lock_irqsave(&cdev->lock, flags);
if (!android_device)
return 0;
gi = dev_get_drvdata(android_device);
spin_lock_irqsave(&gi->spinlock, flags);
cdev = get_gadget_data(gadget);
if (!cdev || gi->unbind) {
spin_unlock_irqrestore(&gi->spinlock, flags);
return 0;
}
if (!gi->connected) {
gi->connected = 1;
schedule_work(&gi->work);
}
spin_unlock_irqrestore(&cdev->lock, flags);
list_for_each_entry(fi, &gi->available_func, cfs_list) {
if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
value = fi->f->setup(fi->f, c);
@ -1562,12 +1572,11 @@ static int android_setup(struct usb_gadget *gadget,
if (value < 0)
value = composite_setup(gadget, c);
spin_lock_irqsave(&cdev->lock, flags);
if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
cdev->config) {
schedule_work(&gi->work);
}
spin_unlock_irqrestore(&cdev->lock, flags);
spin_unlock_irqrestore(&gi->spinlock, flags);
return value;
}