diff options
| author | Alan Stern <stern@rowland.harvard.edu> | 2018-01-03 12:51:51 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-01-09 10:06:53 -0500 |
| commit | 7ae2c3c280db183ca9ada2675c34ec2f7378abfa (patch) | |
| tree | 67af2f403b945235aa311ec41abfe1b2c89a7085 | |
| parent | 46eb14a6e1585d99c1b9f58d0e7389082a5f466b (diff) | |
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>
| -rw-r--r-- | drivers/usb/gadget/udc/core.c | 28 |
1 files changed, 13 insertions, 15 deletions
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, | |||
| 1147 | 1147 | ||
| 1148 | udc = kzalloc(sizeof(*udc), GFP_KERNEL); | 1148 | udc = kzalloc(sizeof(*udc), GFP_KERNEL); |
| 1149 | if (!udc) | 1149 | if (!udc) |
| 1150 | goto err1; | 1150 | goto err_put_gadget; |
| 1151 | |||
| 1152 | ret = device_add(&gadget->dev); | ||
| 1153 | if (ret) | ||
| 1154 | goto err2; | ||
| 1155 | 1151 | ||
| 1156 | device_initialize(&udc->dev); | 1152 | device_initialize(&udc->dev); |
| 1157 | udc->dev.release = usb_udc_release; | 1153 | udc->dev.release = usb_udc_release; |
| @@ -1160,7 +1156,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, | |||
| 1160 | udc->dev.parent = parent; | 1156 | udc->dev.parent = parent; |
| 1161 | ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); | 1157 | ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); |
| 1162 | if (ret) | 1158 | if (ret) |
| 1163 | goto err3; | 1159 | goto err_put_udc; |
| 1160 | |||
| 1161 | ret = device_add(&gadget->dev); | ||
| 1162 | if (ret) | ||
| 1163 | goto err_put_udc; | ||
| 1164 | 1164 | ||
| 1165 | udc->gadget = gadget; | 1165 | udc->gadget = gadget; |
| 1166 | gadget->udc = udc; | 1166 | gadget->udc = udc; |
| @@ -1170,7 +1170,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, | |||
| 1170 | 1170 | ||
| 1171 | ret = device_add(&udc->dev); | 1171 | ret = device_add(&udc->dev); |
| 1172 | if (ret) | 1172 | if (ret) |
| 1173 | goto err4; | 1173 | goto err_unlist_udc; |
| 1174 | 1174 | ||
| 1175 | usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); | 1175 | usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); |
| 1176 | udc->vbus = true; | 1176 | udc->vbus = true; |
| @@ -1178,27 +1178,25 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, | |||
| 1178 | /* pick up one of pending gadget drivers */ | 1178 | /* pick up one of pending gadget drivers */ |
| 1179 | ret = check_pending_gadget_drivers(udc); | 1179 | ret = check_pending_gadget_drivers(udc); |
| 1180 | if (ret) | 1180 | if (ret) |
| 1181 | goto err5; | 1181 | goto err_del_udc; |
| 1182 | 1182 | ||
| 1183 | mutex_unlock(&udc_lock); | 1183 | mutex_unlock(&udc_lock); |
| 1184 | 1184 | ||
| 1185 | return 0; | 1185 | return 0; |
| 1186 | 1186 | ||
| 1187 | err5: | 1187 | err_del_udc: |
| 1188 | device_del(&udc->dev); | 1188 | device_del(&udc->dev); |
| 1189 | 1189 | ||
| 1190 | err4: | 1190 | err_unlist_udc: |
| 1191 | list_del(&udc->list); | 1191 | list_del(&udc->list); |
| 1192 | mutex_unlock(&udc_lock); | 1192 | mutex_unlock(&udc_lock); |
| 1193 | 1193 | ||
| 1194 | err3: | ||
| 1195 | put_device(&udc->dev); | ||
| 1196 | device_del(&gadget->dev); | 1194 | device_del(&gadget->dev); |
| 1197 | 1195 | ||
| 1198 | err2: | 1196 | err_put_udc: |
| 1199 | kfree(udc); | 1197 | put_device(&udc->dev); |
| 1200 | 1198 | ||
| 1201 | err1: | 1199 | err_put_gadget: |
| 1202 | put_device(&gadget->dev); | 1200 | put_device(&gadget->dev); |
| 1203 | return ret; | 1201 | return ret; |
| 1204 | } | 1202 | } |
