summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2022-03-19 12:02:45 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2022-03-28 10:52:55 +0200
commitfb26c992666331ab250886a08254293b1fa86eba (patch)
tree8da9e14ccff428831d4204e82ab57686dc6e748f /drivers/usb
parentc3dca9f42aba61f0393dda0ba24ef96e792dcd18 (diff)
downloadbarebox-fb26c992666331ab250886a08254293b1fa86eba.tar.gz
barebox-fb26c992666331ab250886a08254293b1fa86eba.tar.xz
usb: gadget: multi: fix broken handling of USB function bind error
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@pengutronix.de> Link: https://lore.barebox.org/20220319110246.2850396-6-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/multi.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 0eb6d049d1..cd5b529d3e 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;
}