On Tue Mar 10 22:14:37 2026 +0530, Abhishek Kumar wrote:
> em28xx_v4l2_open() reads dev->v4l2 without holding dev->lock,
> creating a race with em28xx_v4l2_init()'s error path and
> em28xx_v4l2_fini(), both of which free the em28xx_v4l2 struct
> and set dev->v4l2 to NULL under dev->lock.
> 
> This race leads to two issues:
>  - use-after-free in v4l2_fh_init() when accessing vdev->ctrl_handler,
>    since the video_device is embedded in the freed em28xx_v4l2 struct.
>  - NULL pointer dereference in em28xx_resolution_set() when accessing
>    v4l2->norm, since dev->v4l2 has been set to NULL.
> 
> Fix this by moving the mutex_lock() before the dev->v4l2 read and
> adding a NULL check for dev->v4l2 under the lock.
> 
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=c025d34b8eaa54c571b8
> Fixes: 8139a4d583ab ("[media] em28xx: move v4l2 user counting fields from 
> struct em28xx to struct v4l2")
> Cc: [email protected]
> Signed-off-by: Abhishek Kumar <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/usb/em28xx/em28xx-video.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

---

diff --git a/drivers/media/usb/em28xx/em28xx-video.c 
b/drivers/media/usb/em28xx/em28xx-video.c
index b0c184f237a7..5f13f63fbdee 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2126,7 +2126,7 @@ static int em28xx_v4l2_open(struct file *filp)
 {
        struct video_device *vdev = video_devdata(filp);
        struct em28xx *dev = video_drvdata(filp);
-       struct em28xx_v4l2 *v4l2 = dev->v4l2;
+       struct em28xx_v4l2 *v4l2;
        enum v4l2_buf_type fh_type = 0;
        int ret;
 
@@ -2143,13 +2143,19 @@ static int em28xx_v4l2_open(struct file *filp)
                return -EINVAL;
        }
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+
+       v4l2 = dev->v4l2;
+       if (!v4l2) {
+               mutex_unlock(&dev->lock);
+               return -ENODEV;
+       }
+
        em28xx_videodbg("open dev=%s type=%s users=%d\n",
                        video_device_node_name(vdev), v4l2_type_names[fh_type],
                        v4l2->users);
 
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-
        ret = v4l2_fh_open(filp);
        if (ret) {
                dev_err(&dev->intf->dev,
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to