[PATCH v2] input: sur40: fix error recovery in sur40_probe()
Dmitry Antipov <[email protected]> Mon, 10 Aug 2026 18:35:09 +0300
| Newsgroups | org.kernel.vger.linux-input |
|---|---|
| Message-ID | <[email protected]> |
Since an input device which has passed 'input_register_device()' should be released with 'input_unregister_device()', adjust 'sur40_probe()' to do so and call 'input_free_device()' to handle device register error only. To avoid V4L2 memory leak, ensure that 'v4l2_ctrl_handler_free()' is called on all error handling paths, including the one after 'video_register_device()' failure. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=2a123f6269da57ffefaa Fixes: 08b936012964 ("Input: sur40 - switch to using polled mode of input devices") Signed-off-by: Dmitry Antipov <[email protected]> --- v2: setup sur40 input device pointer after 'input_register_device()' and adjust error handling path to ensure that 'input_unregister_device()' is always called for a registered device only (Vasileios) --- drivers/input/touchscreen/sur40.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index fe63d53d56db..35a946979cb0 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -713,7 +713,6 @@ static int sur40_probe(struct usb_interface *interface, sur40->usbdev = usbdev; sur40->dev = &interface->dev; - sur40->input = input; /* use the bulk-in endpoint tested above */ sur40->bulk_in_size = usb_endpoint_maxp(endpoint); @@ -733,6 +732,9 @@ static int sur40_probe(struct usb_interface *interface, goto err_free_buffer; } + /* now we have a completely initialized input device */ + sur40->input = input; + /* register the video master device */ snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG); error = v4l2_device_register(sur40->dev, &sur40->v4l2); @@ -786,9 +788,8 @@ static int sur40_probe(struct usb_interface *interface, if (sur40->hdl.error) { dev_err(&interface->dev, "Unable to register video controls."); - v4l2_ctrl_handler_free(&sur40->hdl); error = sur40->hdl.error; - goto err_unreg_v4l2; + goto err_unreg_ctrl; } error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1); @@ -806,12 +807,17 @@ static int sur40_probe(struct usb_interface *interface, err_unreg_video: video_unregister_device(&sur40->vdev); +err_unreg_ctrl: + v4l2_ctrl_handler_free(&sur40->hdl); err_unreg_v4l2: v4l2_device_unregister(&sur40->v4l2); err_free_buffer: kfree(sur40->bulk_in_buffer); err_free_input: - input_free_device(input); + if (sur40->input) + input_unregister_device(input); + else + input_free_device(input); err_free_dev: kfree(sur40); -- 2.55.0