[PATCH] usb: gadget: loopback: fix memory leak on bind failure

From: hanzhijian

Date: Fri Aug 21 2026 - 23:22:04 EST


loopback_bind() assigns descriptors via usb_assign_descriptors() but the
function has no unbind callback, so when configfs_composite_bind() fails
after usb_add_function() succeeds (for example when
usb_gadget_check_config() fails), purge_configs_funcs() only calls the
unbind callback and the descriptors are never freed.

Add an unbind callback that calls usb_free_all_descriptors(), matching
the pattern used by other functions such as f_acm, so the descriptors
are released when the function is unbound.

Reported-by: syzbot+28cf08dec5895bd562e6@xxxxxxxxxxxxxxxxxxxxxxxxx
Link: https://syzkaller.appspot.com/bug?extid=28cf08dec5895bd562e6
Signed-off-by: hanzhijian <hanzhijian1991@xxxxxxxxx>
---
drivers/usb/gadget/function/f_loopback.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
index d2d07fb49..bf4038cfc 100644
--- a/drivers/usb/gadget/function/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
@@ -216,6 +216,11 @@ static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
}

+static void loopback_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ usb_free_all_descriptors(f);
+}
+
static void lb_free_func(struct usb_function *f)
{
struct f_lb_opts *opts;
@@ -442,6 +447,7 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)

loop->function.name = "loopback";
loop->function.bind = loopback_bind;
+ loop->function.unbind = loopback_unbind;
loop->function.set_alt = loopback_set_alt;
loop->function.disable = loopback_disable;
loop->function.strings = loopback_strings;
--
2.43.0