Re: [PATCH] Input: sur40 - fix use-after-free in v4l2_release on disconnect

From: Deepanshu Kartikey

Date: Tue Sep 22 2026 - 23:25:32 EST


On Sat, Sep 12, 2026 at 9:23 AM Deepanshu Kartikey
<kartikey406@xxxxxxxxx> wrote:
>
> sur40_disconnect() unconditionally freed the sur40_state struct
> (which embeds struct video_device vdev) via kfree(), even while a
> userspace process could still hold an open file descriptor on the
> video device. video_unregister_device() does not wait for open file
> descriptors to close before returning, so if a process closed its fd
> after disconnect() had already run, v4l2_release() would dereference
> the already-freed vdev, resulting in a slab-use-after-free.
>
> Fix this by giving vdev a real .release callback (sur40_video_release)
> instead of video_device_release_empty, and move the v4l2_device
> unregister and the kfree() calls into it. This defers the actual free
> until the last reference to vdev drops to zero, whether that happens
> during disconnect() (no fd open) or later when the last open fd is
> closed.
>
> Tested-by: syzbot+34957180b0ed2581edaf@xxxxxxxxxxxxxxxxxxxxxxxxx
> Reported-by: syzbot+34957180b0ed2581edaf@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=34957180b0ed2581edaf
> Assisted-by: Claude
> Signed-off-by: Deepanshu Kartikey <kartikey406@xxxxxxxxx>
> ---
> drivers/input/touchscreen/sur40.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
> index 09d8c5f8d09f..bd8d9f6190fb 100644
> --- a/drivers/input/touchscreen/sur40.c
> +++ b/drivers/input/touchscreen/sur40.c
> @@ -179,6 +179,7 @@ static uint gain = SUR40_GAIN_DEF;
> module_param(gain, uint, 0644);
> MODULE_PARM_DESC(gain, "set initial gain"
> SUR40_PARAM_RANGE(SUR40_GAIN_MIN, SUR40_GAIN_MAX));
> +static void sur40_video_release(struct video_device *vdev);
>
> static const struct v4l2_pix_format sur40_pix_format[] = {
> {
> @@ -750,6 +751,7 @@ static int sur40_probe(struct usb_interface *interface,
> sur40->vdev.v4l2_dev = &sur40->v4l2;
> sur40->vdev.lock = &sur40->lock;
> sur40->vdev.queue = &sur40->queue;
> + sur40->vdev.release = sur40_video_release;
> video_set_drvdata(&sur40->vdev, sur40);
>
> /* initialize the control handler for 4 controls */
> @@ -820,6 +822,16 @@ static int sur40_probe(struct usb_interface *interface,
> return error;
> }
>
> +static void sur40_video_release(struct video_device *vdev)
> +{
> + struct sur40_state *sur40 = container_of(
> + vdev, struct sur40_state, vdev);
> +
> + v4l2_device_unregister(&sur40->v4l2);
> + kfree(sur40->bulk_in_buffer);
> + kfree(sur40);
> +}
> +
> /* Unregister device & clean up. */
> static void sur40_disconnect(struct usb_interface *interface)
> {
> @@ -829,10 +841,6 @@ static void sur40_disconnect(struct usb_interface *interface)
>
> v4l2_ctrl_handler_free(&sur40->hdl);
> video_unregister_device(&sur40->vdev);
> - v4l2_device_unregister(&sur40->v4l2);
> -
> - kfree(sur40->bulk_in_buffer);
> - kfree(sur40);
>
> usb_set_intfdata(interface, NULL);
> dev_dbg(&interface->dev, "%s is now disconnected\n", DRIVER_DESC);
> --
> 2.43.0
>

Gentle Reminder. Please let me know the status of this patch.

Thanks


Deepanshu