Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 8846739f52af ("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>

authored by

Johan Hovold and committed by
Mark Brown
b99e3ddb 762a3847

+25 -11
+25 -11
drivers/spi/spi-ch341.c
··· 173 173 174 174 ch341->tx_buf = 175 175 devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL); 176 - if (!ch341->tx_buf) 177 - return -ENOMEM; 176 + if (!ch341->tx_buf) { 177 + ret = -ENOMEM; 178 + goto err_free_urb; 179 + } 178 180 179 181 usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf, 180 182 ch341->rx_len, ch341_recv, ch341); 181 183 182 184 ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL); 183 - if (ret) { 184 - usb_free_urb(ch341->rx_urb); 185 - return -ENOMEM; 186 - } 185 + if (ret) 186 + goto err_free_urb; 187 187 188 188 ctrl->bus_num = -1; 189 189 ctrl->mode_bits = SPI_CPHA; ··· 195 195 196 196 ret = ch341_config_stream(ch341); 197 197 if (ret) 198 - return ret; 198 + goto err_kill_urb; 199 199 200 200 ret = ch341_enable_pins(ch341, true); 201 201 if (ret) 202 - return ret; 202 + goto err_kill_urb; 203 203 204 204 ret = spi_register_controller(ctrl); 205 205 if (ret) 206 - return ret; 206 + goto err_disable_pins; 207 207 208 208 ch341->spidev = spi_new_device(ctrl, &chip); 209 - if (!ch341->spidev) 210 - return -ENOMEM; 209 + if (!ch341->spidev) { 210 + ret = -ENOMEM; 211 + goto err_unregister; 212 + } 211 213 212 214 return 0; 215 + 216 + err_unregister: 217 + spi_unregister_controller(ctrl); 218 + err_disable_pins: 219 + ch341_enable_pins(ch341, false); 220 + err_kill_urb: 221 + usb_kill_urb(ch341->rx_urb); 222 + err_free_urb: 223 + usb_free_urb(ch341->rx_urb); 224 + 225 + return ret; 213 226 } 214 227 215 228 static void ch341_disconnect(struct usb_interface *intf) ··· 232 219 spi_unregister_device(ch341->spidev); 233 220 spi_unregister_controller(ch341->ctrl); 234 221 ch341_enable_pins(ch341, false); 222 + usb_kill_urb(ch341->rx_urb); 235 223 usb_free_urb(ch341->rx_urb); 236 224 } 237 225