media: vivid: s_fbuf: add more sanity checks
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Wed, 12 Oct 2022 14:32:28 +0000 (15:32 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Nov 2022 14:59:17 +0000 (23:59 +0900)
[ Upstream commit f8bcaf714abfc94818dff8c0db84d750433984f4 ]

VIDIOC_S_FBUF is by definition a scary ioctl, which is why only root
can use it. But at least check if the framebuffer parameters match that
of one of the framebuffer created by vivid, and reject anything else.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Fixes: ef834f7836ec ([media] vivid: add the video capture and output parts)
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/test-drivers/vivid/vivid-core.c
drivers/media/test-drivers/vivid/vivid-core.h
drivers/media/test-drivers/vivid/vivid-vid-cap.c

index d2bd2653cf54dedc2e10dd5891554615c3b85b6f..e7cc70a926834d6dc8419475809308be0c7c58a4 100644 (file)
@@ -330,6 +330,28 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a
        return vivid_vid_out_g_fbuf(file, fh, a);
 }
 
+/*
+ * Only support the framebuffer of one of the vivid instances.
+ * Anything else is rejected.
+ */
+bool vivid_validate_fb(const struct v4l2_framebuffer *a)
+{
+       struct vivid_dev *dev;
+       int i;
+
+       for (i = 0; i < n_devs; i++) {
+               dev = vivid_devs[i];
+               if (!dev || !dev->video_pbase)
+                       continue;
+               if ((unsigned long)a->base == dev->video_pbase &&
+                   a->fmt.width <= dev->display_width &&
+                   a->fmt.height <= dev->display_height &&
+                   a->fmt.bytesperline <= dev->display_byte_stride)
+                       return true;
+       }
+       return false;
+}
+
 static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
 {
        struct video_device *vdev = video_devdata(file);
index 1e3c4f5a9413fe9e0c46693ec5d7178b4e4a9347..7ceaf9bac2f0553e3dae552aeb3255959c2cd6a0 100644 (file)
@@ -610,4 +610,6 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
        return dev->output_type[dev->output] == HDMI;
 }
 
+bool vivid_validate_fb(const struct v4l2_framebuffer *a);
+
 #endif
index b9caa4b26209ef1951d1ef5024e016c89eeb07b9..c9eb28b3a03deb4fd9fc3116eab20330d6fc1ce4 100644 (file)
@@ -1272,7 +1272,14 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
                return -EINVAL;
        if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
                return -EINVAL;
-       if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
+       if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
+               return -EINVAL;
+
+       /*
+        * Only support the framebuffer of one of the vivid instances.
+        * Anything else is rejected.
+        */
+       if (!vivid_validate_fb(a))
                return -EINVAL;
 
        dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);