]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
USB: gadget: f_hid: Fix memory leak in hidg_bind error path
authorYuhao Jiang <danisjiang@gmail.com>
Mon, 23 Jun 2025 09:48:44 +0000 (17:48 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Aug 2025 10:14:14 +0000 (12:14 +0200)
commit 62783c30d78aecf9810dae46fd4d11420ad38b74 upstream.

In hidg_bind(), if alloc_workqueue() fails after usb_assign_descriptors()
has successfully allocated the USB descriptors, the current error handling
does not call usb_free_all_descriptors() to free the allocated descriptors,
resulting in a memory leak.

Restructure the error handling by adding proper cleanup labels:
- fail_free_all: cleans up workqueue and descriptors
- fail_free_descs: cleans up descriptors only
- fail: original cleanup for earlier failures

This ensures that allocated resources are properly freed in reverse order
of their allocation, preventing the memory leak when alloc_workqueue() fails.

Fixes: a139c98f760ef ("USB: gadget: f_hid: Add GET_REPORT via userspace IOCTL")
Cc: stable@vger.kernel.org
Signed-off-by: Yuhao Jiang <danisjiang@gmail.com>
Link: https://lore.kernel.org/r/20250623094844.244977-1-danisjiang@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/function/f_hid.c

index d8bd2d82e9ec63ea5a2cac6ebd10e9100130671f..ab4d170469f5781eba2691d9b42da83e08eedcda 100644 (file)
@@ -1275,18 +1275,19 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
 
        if (!hidg->workqueue) {
                status = -ENOMEM;
-               goto fail;
+               goto fail_free_descs;
        }
 
        /* create char device */
        cdev_init(&hidg->cdev, &f_hidg_fops);
        status = cdev_device_add(&hidg->cdev, &hidg->dev);
        if (status)
-               goto fail_free_descs;
+               goto fail_free_all;
 
        return 0;
-fail_free_descs:
+fail_free_all:
        destroy_workqueue(hidg->workqueue);
+fail_free_descs:
        usb_free_all_descriptors(f);
 fail:
        ERROR(f->config->cdev, "hidg_bind FAILED\n");