diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 6b84c3413e83..a1bf488af4fb 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2153,13 +2153,17 @@ static int em28xx_v4l2_open(struct file *filp)
 		return -EINVAL;
 	}
 
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+	if (!dev->v4l2) {
+		mutex_unlock(&dev->lock);
+		return -ENOMEM;
+	}
+
 	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,
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index a593ea0598b5..4687a5761845 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -424,6 +424,15 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 		else
 			ret = -ENODEV;
 	}
+	/*
+	 * when vdev is a nested struct in some driver's struct, video_get() has no effect and
+	 * referencing vdev might cause UAF, therefore, after returning from open()  we need to
+	 * check whether vdev has already been freed as part of a parent struct, after returning
+	 * from open()
+	 */
+	mutex_lock(&videodev_lock);
+	if (!video_devdata(filp) && ret)
+		goto out;
 
 	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
 		dprintk("%s: open (%d)\n",
@@ -431,6 +440,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 	/* decrease the refcount in case of an error */
 	if (ret)
 		video_put(vdev);
+out:
+	mutex_unlock(&videodev_lock);
 	return ret;
 }