* [PATCH v1 1/2] Input: sur40 - don't wait for buffers nothing will complete [not found] <20260920113949.12726-1-ngocthang2710.1999@gmail.com> @ 2026-09-20 11:39 ` Nguyen Ngoc Thang 2026-09-30 8:04 ` Hans Verkuil 2026-09-20 11:39 ` [PATCH v1 2/2] Input: sur40 - keep device state alive until the video node is released Nguyen Ngoc Thang 1 sibling, 1 reply; 4+ messages in thread From: Nguyen Ngoc Thang @ 2026-09-20 11:39 UTC (permalink / raw) To: dmitry.torokhov Cc: floe, linux-input, linux-media, linux-kernel, Nguyen Ngoc Thang, stable sur40_stop_streaming() calls vb2_wait_for_all_buffers() before handing the queued buffers back. Those buffers are only completed from the input poll callback, which is gone once the device is unplugged. Closing a video node that is still streaming after a disconnect then sleeps forever in vb2_wait_for_all_buffers(): vb2_wait_for_all_buffers+0x20f/0x330 sur40_stop_streaming+0x45/0x310 __vb2_queue_cancel+0xc5/0xf70 vb2_core_streamoff+0x5d/0x180 __vb2_cleanup_fileio+0x6e/0x190 vb2_core_queue_release+0x1f/0x190 _vb2_fop_release+0xe8/0x280 v4l2_release+0x280/0x430 It has not been noticed so far because sur40_disconnect() frees the device state under the open file, and the close then crashes earlier. Return the queued buffers first. A buffer that sur40_process_video() has already taken off the list still completes by itself, so the wait afterwards only covers that one. Fixes: 6a8588156657 ("[media] sur40: fix occasional oopses on device close") Cc: stable@vger.kernel.org Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> --- drivers/input/touchscreen/sur40.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 09d8c5f8d09f..7020bcf9b81a 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -929,11 +929,11 @@ static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count) static void sur40_stop_streaming(struct vb2_queue *vq) { struct sur40_state *sur40 = vb2_get_drv_priv(vq); - vb2_wait_for_all_buffers(vq); - sur40->sequence = -1; - /* Release all active buffers */ + /* Release queued buffers first: nothing completes them after unplug */ return_all_buffers(sur40, VB2_BUF_STATE_ERROR); + vb2_wait_for_all_buffers(vq); + sur40->sequence = -1; } /* V4L ioctl */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v1 1/2] Input: sur40 - don't wait for buffers nothing will complete 2026-09-20 11:39 ` [PATCH v1 1/2] Input: sur40 - don't wait for buffers nothing will complete Nguyen Ngoc Thang @ 2026-09-30 8:04 ` Hans Verkuil 0 siblings, 0 replies; 4+ messages in thread From: Hans Verkuil @ 2026-09-30 8:04 UTC (permalink / raw) To: Nguyen Ngoc Thang, dmitry.torokhov Cc: floe, linux-input, linux-media, linux-kernel, stable On 20/09/2026 13:39, Nguyen Ngoc Thang wrote: > sur40_stop_streaming() calls vb2_wait_for_all_buffers() before handing > the queued buffers back. Those buffers are only completed from the input > poll callback, which is gone once the device is unplugged. Closing a > video node that is still streaming after a disconnect then sleeps > forever in vb2_wait_for_all_buffers(): > > vb2_wait_for_all_buffers+0x20f/0x330 > sur40_stop_streaming+0x45/0x310 > __vb2_queue_cancel+0xc5/0xf70 > vb2_core_streamoff+0x5d/0x180 > __vb2_cleanup_fileio+0x6e/0x190 > vb2_core_queue_release+0x1f/0x190 > _vb2_fop_release+0xe8/0x280 > v4l2_release+0x280/0x430 > > It has not been noticed so far because sur40_disconnect() frees the > device state under the open file, and the close then crashes earlier. > > Return the queued buffers first. A buffer that sur40_process_video() > has already taken off the list still completes by itself, so the wait > afterwards only covers that one. > > Fixes: 6a8588156657 ("[media] sur40: fix occasional oopses on device close") > Cc: stable@vger.kernel.org > Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> > --- > drivers/input/touchscreen/sur40.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c > index 09d8c5f8d09f..7020bcf9b81a 100644 > --- a/drivers/input/touchscreen/sur40.c > +++ b/drivers/input/touchscreen/sur40.c > @@ -929,11 +929,11 @@ static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count) > static void sur40_stop_streaming(struct vb2_queue *vq) > { > struct sur40_state *sur40 = vb2_get_drv_priv(vq); > - vb2_wait_for_all_buffers(vq); > - sur40->sequence = -1; > > - /* Release all active buffers */ > + /* Release queued buffers first: nothing completes them after unplug */ > return_all_buffers(sur40, VB2_BUF_STATE_ERROR); > + vb2_wait_for_all_buffers(vq); > + sur40->sequence = -1; > } > > /* V4L ioctl */ I think you should make one more change: replace the video_unregister_device calls by vb2_video_unregister_device(). This ensures that at unregister time all streaming is canceled and stop_streaming is called. Having streaming continue after unregistering a device is in general not a good idea, which is why we added that vb2_video_unregister_device call. I think you still need to have that change in stop_streaming for this specific driver, but it might be worth testing without it. Regards, Hans ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 2/2] Input: sur40 - keep device state alive until the video node is released [not found] <20260920113949.12726-1-ngocthang2710.1999@gmail.com> 2026-09-20 11:39 ` [PATCH v1 1/2] Input: sur40 - don't wait for buffers nothing will complete Nguyen Ngoc Thang @ 2026-09-20 11:39 ` Nguyen Ngoc Thang 2026-09-30 8:05 ` Hans Verkuil 1 sibling, 1 reply; 4+ messages in thread From: Nguyen Ngoc Thang @ 2026-09-20 11:39 UTC (permalink / raw) To: dmitry.torokhov Cc: floe, linux-input, linux-media, linux-kernel, Nguyen Ngoc Thang, syzbot+eb4706daf505f9c4b547, stable sur40_disconnect() frees the sur40_state, which embeds the video_device, the v4l2_device and the vb2_queue, while a video node may still be open. Closing that file afterwards touches freed memory: BUG: KASAN: slab-use-after-free in vb2_core_queue_release+0x12d/0x150 Read of size 4 at addr ffff888066fa8aa8 by task v4l_id/28733 vb2_core_queue_release+0x12d/0x150 vb2_fop_release+0x16e/0x200 v4l2_release+0x22c/0x350 __fput+0x418/0xa50 Freed by task 16811: kfree+0x1c5/0x650 sur40_disconnect+0xaf/0x140 Give the v4l2_device a release callback that frees the bulk buffer and the state, and drop the disconnect path's own reference with v4l2_device_put(). The last closer of the node then does the freeing. The probe error paths never open the node and keep freeing directly. Reported-by: syzbot+eb4706daf505f9c4b547@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=eb4706daf505f9c4b547 Fixes: e831cd251fb9 ("[media] add raw video stream support for Samsung SUR40") Cc: stable@vger.kernel.org Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> --- drivers/input/touchscreen/sur40.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 7020bcf9b81a..efd4fe557cef 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -648,6 +648,15 @@ static int sur40_input_setup_events(struct input_dev *input_dev) } /* Check candidate USB interface. */ +/* Runs once the last video node reference is gone. */ +static void sur40_release(struct v4l2_device *v4l2) +{ + struct sur40_state *sur40 = container_of(v4l2, struct sur40_state, v4l2); + + kfree(sur40->bulk_in_buffer); + kfree(sur40); +} + static int sur40_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -733,6 +742,7 @@ static int sur40_probe(struct usb_interface *interface, "Unable to register video master device."); goto err_free_buffer; } + sur40->v4l2.release = sur40_release; /* initialize the lock and subdevice */ sur40->queue = sur40_queue; @@ -831,11 +841,10 @@ static void sur40_disconnect(struct usb_interface *interface) 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); + + v4l2_device_put(&sur40->v4l2); } /* -- 2.43.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v1 2/2] Input: sur40 - keep device state alive until the video node is released 2026-09-20 11:39 ` [PATCH v1 2/2] Input: sur40 - keep device state alive until the video node is released Nguyen Ngoc Thang @ 2026-09-30 8:05 ` Hans Verkuil 0 siblings, 0 replies; 4+ messages in thread From: Hans Verkuil @ 2026-09-30 8:05 UTC (permalink / raw) To: Nguyen Ngoc Thang, dmitry.torokhov Cc: floe, linux-input, linux-media, linux-kernel, syzbot+eb4706daf505f9c4b547, stable On 20/09/2026 13:39, Nguyen Ngoc Thang wrote: > sur40_disconnect() frees the sur40_state, which embeds the video_device, > the v4l2_device and the vb2_queue, while a video node may still be open. > Closing that file afterwards touches freed memory: > > BUG: KASAN: slab-use-after-free in vb2_core_queue_release+0x12d/0x150 > Read of size 4 at addr ffff888066fa8aa8 by task v4l_id/28733 > vb2_core_queue_release+0x12d/0x150 > vb2_fop_release+0x16e/0x200 > v4l2_release+0x22c/0x350 > __fput+0x418/0xa50 > Freed by task 16811: > kfree+0x1c5/0x650 > sur40_disconnect+0xaf/0x140 > > Give the v4l2_device a release callback that frees the bulk buffer and > the state, and drop the disconnect path's own reference with > v4l2_device_put(). The last closer of the node then does the freeing. > The probe error paths never open the node and keep freeing directly. > > Reported-by: syzbot+eb4706daf505f9c4b547@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=eb4706daf505f9c4b547 > Fixes: e831cd251fb9 ("[media] add raw video stream support for Samsung SUR40") > Cc: stable@vger.kernel.org > Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> Reviewed-by: Hans Verkuil <hverkuil+cisco@kernel.org> Regards, Hans > --- > drivers/input/touchscreen/sur40.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c > index 7020bcf9b81a..efd4fe557cef 100644 > --- a/drivers/input/touchscreen/sur40.c > +++ b/drivers/input/touchscreen/sur40.c > @@ -648,6 +648,15 @@ static int sur40_input_setup_events(struct input_dev *input_dev) > } > > /* Check candidate USB interface. */ > +/* Runs once the last video node reference is gone. */ > +static void sur40_release(struct v4l2_device *v4l2) > +{ > + struct sur40_state *sur40 = container_of(v4l2, struct sur40_state, v4l2); > + > + kfree(sur40->bulk_in_buffer); > + kfree(sur40); > +} > + > static int sur40_probe(struct usb_interface *interface, > const struct usb_device_id *id) > { > @@ -733,6 +742,7 @@ static int sur40_probe(struct usb_interface *interface, > "Unable to register video master device."); > goto err_free_buffer; > } > + sur40->v4l2.release = sur40_release; > > /* initialize the lock and subdevice */ > sur40->queue = sur40_queue; > @@ -831,11 +841,10 @@ static void sur40_disconnect(struct usb_interface *interface) > 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); > + > + v4l2_device_put(&sur40->v4l2); > } > > /* ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-30 8:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260920113949.12726-1-ngocthang2710.1999@gmail.com>
2026-09-20 11:39 ` [PATCH v1 1/2] Input: sur40 - don't wait for buffers nothing will complete Nguyen Ngoc Thang
2026-09-30 8:04 ` Hans Verkuil
2026-09-20 11:39 ` [PATCH v1 2/2] Input: sur40 - keep device state alive until the video node is released Nguyen Ngoc Thang
2026-09-30 8:05 ` Hans Verkuil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox