The patch below does not apply to the 4.9-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7ae2c3c280db183ca9ada2675c34ec2f7378abfa Mon Sep 17 00:00:00 2001
From: Alan Stern stern@rowland.harvard.edu Date: Wed, 3 Jan 2018 12:51:51 -0500 Subject: [PATCH] USB: UDC core: fix double-free in usb_add_gadget_udc_release
The error-handling pathways in usb_add_gadget_udc_release() are messed up. Aside from the uninformative statement labels, they can deallocate the udc structure after calling put_device(), which is a double-free. This was observed by KASAN in automatic testing.
This patch cleans up the routine. It preserves the requirement that when any failure occurs, we call put_device(&gadget->dev).
Signed-off-by: Alan Stern stern@rowland.harvard.edu Reported-by: Fengguang Wu fengguang.wu@intel.com CC: stable@vger.kernel.org Reviewed-by: Peter Chen peter.chen@nxp.com Acked-by: Felipe Balbi felipe.balbi@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 93eff7dec2f5..1b3efb14aec7 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1147,11 +1147,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
udc = kzalloc(sizeof(*udc), GFP_KERNEL); if (!udc) - goto err1; - - ret = device_add(&gadget->dev); - if (ret) - goto err2; + goto err_put_gadget;
device_initialize(&udc->dev); udc->dev.release = usb_udc_release; @@ -1160,7 +1156,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, udc->dev.parent = parent; ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); if (ret) - goto err3; + goto err_put_udc; + + ret = device_add(&gadget->dev); + if (ret) + goto err_put_udc;
udc->gadget = gadget; gadget->udc = udc; @@ -1170,7 +1170,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
ret = device_add(&udc->dev); if (ret) - goto err4; + goto err_unlist_udc;
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); udc->vbus = true; @@ -1178,27 +1178,25 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, /* pick up one of pending gadget drivers */ ret = check_pending_gadget_drivers(udc); if (ret) - goto err5; + goto err_del_udc;
mutex_unlock(&udc_lock);
return 0;
-err5: + err_del_udc: device_del(&udc->dev);
-err4: + err_unlist_udc: list_del(&udc->list); mutex_unlock(&udc_lock);
-err3: - put_device(&udc->dev); device_del(&gadget->dev);
-err2: - kfree(udc); + err_put_udc: + put_device(&udc->dev);
-err1: + err_put_gadget: put_device(&gadget->dev); return ret; }
linux-stable-mirror@lists.linaro.org