| From aec17e1e249567e82b26dafbb86de7d07fde8729 Mon Sep 17 00:00:00 2001 |
| From: Andrew Gabbasov <andrew_gabbasov@mentor.com> |
| Date: Sat, 30 Sep 2017 08:55:55 -0700 |
| Subject: usb: gadget: composite: Fix use-after-free in usb_composite_overwrite_options |
| |
| From: Andrew Gabbasov <andrew_gabbasov@mentor.com> |
| |
| commit aec17e1e249567e82b26dafbb86de7d07fde8729 upstream. |
| |
| KASAN enabled configuration reports an error |
| |
| BUG: KASAN: use-after-free in usb_composite_overwrite_options+... |
| [libcomposite] at addr ... |
| Read of size 1 by task ... |
| |
| when some driver is un-bound and then bound again. |
| For example, this happens with FunctionFS driver when "ffs-test" |
| test application is run several times in a row. |
| |
| If the driver has empty manufacturer ID string in initial static data, |
| it is then replaced with generated string. After driver unbinding |
| the generated string is freed, but the driver data still keep that |
| pointer. And if the driver is then bound again, that pointer |
| is re-used for string emptiness check. |
| |
| The fix is to clean up the driver string data upon its unbinding |
| to drop the pointer to freed memory. |
| |
| Fixes: cc2683c318a5 ("usb: gadget: Provide a default implementation of default manufacturer string") |
| Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com> |
| Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/gadget/composite.c | 5 +++++ |
| 1 file changed, 5 insertions(+) |
| |
| --- a/drivers/usb/gadget/composite.c |
| +++ b/drivers/usb/gadget/composite.c |
| @@ -1806,6 +1806,8 @@ static DEVICE_ATTR_RO(suspended); |
| static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) |
| { |
| struct usb_composite_dev *cdev = get_gadget_data(gadget); |
| + struct usb_gadget_strings *gstr = cdev->driver->strings[0]; |
| + struct usb_string *dev_str = gstr->strings; |
| |
| /* composite_disconnect() must already have been called |
| * by the underlying peripheral controller driver! |
| @@ -1825,6 +1827,9 @@ static void __composite_unbind(struct us |
| |
| composite_dev_cleanup(cdev); |
| |
| + if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer) |
| + dev_str[USB_GADGET_MANUFACTURER_IDX].s = ""; |
| + |
| kfree(cdev->def_manufacturer); |
| kfree(cdev); |
| set_gadget_data(gadget, NULL); |