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

Ahmad Fatoum a.fatoum at pengutronix.de
Sat Mar 19 04:02:45 PDT 2022


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 at pengutronix.de>
---
 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




More information about the barebox mailing list