summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhishek Kumar <abhishek_sts8@yahoo.com>2026-03-10 22:14:37 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-04-22 13:30:51 +0200
commit6b9e66437cc6123ddedac141e1b8b6fcf57d2972 (patch)
tree50c8d5c2357df2f76d6618ccd158aa20f64bd79b
parent93d9a58961a9e09306857e999b3ee76aa4be67f0 (diff)
downloadlinux-stable-6b9e66437cc6123ddedac141e1b8b6fcf57d2972.tar.gz
linux-stable-6b9e66437cc6123ddedac141e1b8b6fcf57d2972.zip
media: em28xx: fix use-after-free in em28xx_v4l2_open()
commit a66485a934c7187ae8e36517d40615fa2e961cff upstream. 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: syzbot+c025d34b8eaa54c571b8@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c025d34b8eaa54c571b8 Fixes: 8139a4d583ab ("[media] em28xx: move v4l2 user counting fields from struct em28xx to struct v4l2") Cc: stable@vger.kernel.org Signed-off-by: Abhishek Kumar <abhishek_sts8@yahoo.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 2dfa3242a7ab..14c35995cd95 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,