[PATCH master 5/6] usb: gadget: multi: fix broken handling of USB function bind error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If a function of a multi gadget fails, we run into multiple bugs:

  - All gadget are unbound, even those which weren't bound yet
  - We deallocate functions and function instances, but don't
    remove them from USB configuration, which leads to
    use-after-free when doing the composite unbind later on

The correct course of action here is to undo the function instance
allocation only, like Linux does. The rest will be cleaned up later
at composite gadget unbind time.

Fixes: bfb7aa1e1916 ("USB: gadget: Add a multi function gadget")
Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx>
---
 drivers/usb/gadget/multi.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 0eb6d049d152..cd5b529d3eba 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -218,28 +218,28 @@ static int multi_bind(struct usb_composite_dev *cdev)
 		printf("%s: creating Fastboot function\n", __func__);
 		ret = multi_bind_fastboot(cdev);
 		if (ret)
-			goto out;
+			return ret;
 	}
 
 	if (gadget_multi_opts->dfu_opts.files) {
 		printf("%s: creating DFU function\n", __func__);
 		ret = multi_bind_dfu(cdev);
 		if (ret)
-			goto out;
+			goto unbind_fastboot;
 	}
 
 	if (gadget_multi_opts->ums_opts.files) {
 		printf("%s: creating USB Mass Storage function\n", __func__);
 		ret = multi_bind_ums(cdev);
 		if (ret)
-			goto out;
+			goto unbind_dfu;
 	}
 
 	if (gadget_multi_opts->create_acm) {
 		printf("%s: creating ACM function\n", __func__);
 		ret = multi_bind_acm(cdev);
 		if (ret)
-			goto out;
+			goto unbind_ums;
 	}
 
 	usb_ep_autoconfig_reset(cdev->gadget);
@@ -247,8 +247,15 @@ static int multi_bind(struct usb_composite_dev *cdev)
 	dev_info(&gadget->dev, DRIVER_DESC "\n");
 
 	return 0;
-out:
-	multi_unbind(cdev);
+unbind_ums:
+	if (gadget_multi_opts->ums_opts.files)
+		usb_put_function_instance(fi_ums);
+unbind_dfu:
+	if (gadget_multi_opts->dfu_opts.files)
+		usb_put_function_instance(fi_dfu);
+unbind_fastboot:
+	if (gadget_multi_opts->fastboot_opts.files)
+		usb_put_function_instance(fi_fastboot);
 
 	return ret;
 }
-- 
2.30.2


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux