usbserial -d may be called more than once, which now results in removal of a driver that may already be removed leading to double frees. usbgadget -d doesn't suffer from this as both usb_multi_register and usb_multi_unregister keep around a global variable to check if the gadget is currently registered. Let's do likewise for usb_serial_unregister. Fixes: 14211ab8b0e1 ("usb: gadget: Update core to Linux-6.3-rc2") Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- drivers/usb/gadget/legacy/serial.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c index 46c41f6dea30..913d174a9177 100644 --- a/drivers/usb/gadget/legacy/serial.c +++ b/drivers/usb/gadget/legacy/serial.c @@ -247,8 +247,17 @@ static struct usb_composite_driver gserial_driver = { .unbind = gs_unbind, }; +static bool usb_serial_registered; + int usb_serial_register(struct usb_serial_pdata *pdata) { + int ret; + + if (usb_serial_registered) { + pr_err("USB serial gadget already registered\n"); + return -EBUSY; + } + /* We *could* export two configs; that'd be much cleaner... * but neither of these product IDs was defined that way. */ @@ -273,10 +282,18 @@ int usb_serial_register(struct usb_serial_pdata *pdata) device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; } - return usb_composite_probe(&gserial_driver); + ret = usb_composite_probe(&gserial_driver); + if (!ret) + usb_serial_registered = true; + + return ret; } void usb_serial_unregister(void) { + if (!usb_serial_registered) + return; + usb_composite_unregister(&gserial_driver); + usb_serial_registered = false; } -- 2.39.2