spi: ch341: fix memory leaks on probe failures

Make sure to deregister the controller, disable pins, and kill and free
the RX URB on probe failures to mirror disconnect and avoid memory
leaks and use-after-free.

Also add an explicit URB kill on disconnect for symmetry (even if that
is not strictly required as USB core would have stopped it in the
current setup).

Fixes: 8846739f52 ("spi: add ch341a usb2spi driver")
Cc: stable@vger.kernel.org	# 6.11
Cc: Johannes Thumshirn <jth@kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260327104305.1309915-2-johan@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Johan Hovold 2026-03-27 11:43:04 +01:00 committed by Mark Brown
parent 762a3847a0
commit b99e3ddb91
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -173,17 +173,17 @@ static int ch341_probe(struct usb_interface *intf,
ch341->tx_buf =
devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL);
if (!ch341->tx_buf)
return -ENOMEM;
if (!ch341->tx_buf) {
ret = -ENOMEM;
goto err_free_urb;
}
usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf,
ch341->rx_len, ch341_recv, ch341);
ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL);
if (ret) {
usb_free_urb(ch341->rx_urb);
return -ENOMEM;
}
if (ret)
goto err_free_urb;
ctrl->bus_num = -1;
ctrl->mode_bits = SPI_CPHA;
@ -195,21 +195,34 @@ static int ch341_probe(struct usb_interface *intf,
ret = ch341_config_stream(ch341);
if (ret)
return ret;
goto err_kill_urb;
ret = ch341_enable_pins(ch341, true);
if (ret)
return ret;
goto err_kill_urb;
ret = spi_register_controller(ctrl);
if (ret)
return ret;
goto err_disable_pins;
ch341->spidev = spi_new_device(ctrl, &chip);
if (!ch341->spidev)
return -ENOMEM;
if (!ch341->spidev) {
ret = -ENOMEM;
goto err_unregister;
}
return 0;
err_unregister:
spi_unregister_controller(ctrl);
err_disable_pins:
ch341_enable_pins(ch341, false);
err_kill_urb:
usb_kill_urb(ch341->rx_urb);
err_free_urb:
usb_free_urb(ch341->rx_urb);
return ret;
}
static void ch341_disconnect(struct usb_interface *intf)
@ -219,6 +232,7 @@ static void ch341_disconnect(struct usb_interface *intf)
spi_unregister_device(ch341->spidev);
spi_unregister_controller(ch341->ctrl);
ch341_enable_pins(ch341, false);
usb_kill_urb(ch341->rx_urb);
usb_free_urb(ch341->rx_urb);
}