aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Gabbasov <andrew_gabbasov@mentor.com>2017-09-30 11:55:55 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2017-10-11 06:14:30 -0400
commitaec17e1e249567e82b26dafbb86de7d07fde8729 (patch)
tree9925bd20ffe7f0962bcfaf201b4e0872cfa7e523
parentcb84f56861eb333af0a5bab475d741b13067c05c (diff)
usb: gadget: composite: Fix use-after-free in usb_composite_overwrite_options
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") Cc: stable@vger.kernel.org Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/gadget/composite.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index dd74c99d6ce1..5d061b3d8224 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2026,6 +2026,8 @@ static DEVICE_ATTR_RO(suspended);
2026static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) 2026static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
2027{ 2027{
2028 struct usb_composite_dev *cdev = get_gadget_data(gadget); 2028 struct usb_composite_dev *cdev = get_gadget_data(gadget);
2029 struct usb_gadget_strings *gstr = cdev->driver->strings[0];
2030 struct usb_string *dev_str = gstr->strings;
2029 2031
2030 /* composite_disconnect() must already have been called 2032 /* composite_disconnect() must already have been called
2031 * by the underlying peripheral controller driver! 2033 * by the underlying peripheral controller driver!
@@ -2045,6 +2047,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
2045 2047
2046 composite_dev_cleanup(cdev); 2048 composite_dev_cleanup(cdev);
2047 2049
2050 if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer)
2051 dev_str[USB_GADGET_MANUFACTURER_IDX].s = "";
2052
2048 kfree(cdev->def_manufacturer); 2053 kfree(cdev->def_manufacturer);
2049 kfree(cdev); 2054 kfree(cdev);
2050 set_gadget_data(gadget, NULL); 2055 set_gadget_data(gadget, NULL);