Re: [syzbot] [media?] KASAN: slab-use-after-free Read in em28xx_release_resources

Edward Adam Davis
2026-01-11T04:46:16Z

#syz test

diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 2dfa3242a7ab..490ac7548fa3 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -882,9 +882,12 @@ static void em28xx_v4l2_media_release(struct em28xx *dev)

for (i = 0; i < MAX_EM28XX_INPUT; i++) {
if (!INPUT(i)->type)
- return;
+ break;
media_device_unregister_entity(&dev->input_ent[i]);
}
+ media_device_unregister_entity(&dev->v4l2->vdev.entity);
+ if (em28xx_vbi_supported(dev))
+ media_device_unregister_entity(&dev->v4l2->vbi_dev.entity);
#endif
}

@@ -2126,10 +2129,19 @@ 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;

+ if (mutex_lock_interruptible(&dev->lock))
+ return -ERESTARTSYS;
+
+ v4l2 = dev->v4l2;
+ if (!v4l2) {
+ mutex_unlock(&dev->lock);
+ return -EIO;
+ }
+
switch (vdev->vfl_type) {
case VFL_TYPE_VIDEO:
fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -2140,6 +2152,7 @@ static int em28xx_v4l2_open(struct file *filp)
case VFL_TYPE_RADIO:
break;
default:
+ mutex_unlock(&dev->lock);
return -EINVAL;
}

@@ -2147,8 +2160,6 @@ static int em28xx_v4l2_open(struct file *filp)
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) {
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 10a126e50c1c..72dd761d6ec8 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -441,6 +441,9 @@ static int v4l2_open(struct inode *inode, struct file *filp)
}

done:
+ if (ret == -EIO)
+ return ret;
+
if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
dprintk("%s: open (%d)\n",
video_device_node_name(vdev), ret);