diff options
author | Yongsul Oh <yongsul96.oh@samsung.com> | 2012-03-19 21:38:38 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-05-04 08:53:06 -0400 |
commit | 124ef389256f71042ab5dedde98dee5e9999a635 (patch) | |
tree | 1473efbd86a1e4c30c87dcd66b0bd9365daba493 | |
parent | c2484606a105e35a9bbbfafa41ee32683b82cf5a (diff) |
usb: gadget: composite: prevent a memory leak when configuration bind fails
In some USB composite gadget drivers, the configuration's bind function called
by the usb_add_config() calls multiple bind config functions. (for example cdc2
configuration bind function in the cdc_do_config() of the cdc2.c has two
functionality bind config functions.
- the ecm_bind_config() & the acm_bind_config())
In each functionality bind config function, new instance is allocated and
finally added by the usb_add_function().
So if an error occurred during the second functionality bind config (for
example an error occurred at the acm_bind_config() after succeeding of the
ecm_bind_function()), the instance created by the acm_bind_config() cannot be
freed creating a memory leak.
This patch fixes this issue.
Signed-off-by: Yongsul Oh <yongsul96.oh@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/composite.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index baaebf2830fc..4cb1801539a6 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -737,6 +737,19 @@ int usb_add_config(struct usb_composite_dev *cdev, | |||
737 | 737 | ||
738 | status = bind(config); | 738 | status = bind(config); |
739 | if (status < 0) { | 739 | if (status < 0) { |
740 | while (!list_empty(&config->functions)) { | ||
741 | struct usb_function *f; | ||
742 | |||
743 | f = list_first_entry(&config->functions, | ||
744 | struct usb_function, list); | ||
745 | list_del(&f->list); | ||
746 | if (f->unbind) { | ||
747 | DBG(cdev, "unbind function '%s'/%p\n", | ||
748 | f->name, f); | ||
749 | f->unbind(config, f); | ||
750 | /* may free memory for "f" */ | ||
751 | } | ||
752 | } | ||
740 | list_del(&config->list); | 753 | list_del(&config->list); |
741 | config->cdev = NULL; | 754 | config->cdev = NULL; |
742 | } else { | 755 | } else { |