[lvc-project] [PATCH v3] Input: sur40: fix error recovery in sur40_probe()
Dmitry Antipov
dmantipov at yandex.ru
Tue Aug 11 09:44:04 MSK 2026
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. Finally,
since 'sur40_poll()' which reads 'bulk_in_buffer' may become active
immediately after 'input_register_device()' has succeeded, ensure
that this buffer is freed after 'input_unregister_device()', just
like it's done in 'sur40_disconnect()'.
Reported-by: syzbot+2a123f6269da57ffefaa at syzkaller.appspotmail.com
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 <dmantipov at yandex.ru>
---
v3: free 'bulk_in_buffer' after an input device has passed
'input_unregister_device()' (Sashiko)
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 | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index fe63d53d56db..f7d6d89a028b 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);
@@ -730,9 +729,12 @@ static int sur40_probe(struct usb_interface *interface,
if (error) {
dev_err(&interface->dev,
"Unable to register polled input device.");
- goto err_free_buffer;
+ goto err_free_input;
}
+ /* announce an input device as completely initialized */
+ 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,19 @@ 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)
+ /* device was successfully registered */
+ input_unregister_device(input);
+ else
+ /* device just needs to be freed */
+ input_free_device(input);
+ /* this should be done after unregistering an input device */
+ kfree(sur40->bulk_in_buffer);
err_free_dev:
kfree(sur40);
--
2.55.0
More information about the lvc-project
mailing list