media: vivid: dev->bitmap_cap wasn't freed in all cases
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Thu, 13 Oct 2022 14:18:46 +0000 (15:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Nov 2022 14:59:17 +0000 (23:59 +0900)
[ Upstream commit 1f65ea411cc7b6ff128d82a3493d7b5648054e6f ]

Whenever the compose width/height values change, the dev->bitmap_cap
vmalloc'ed array must be freed and dev->bitmap_cap set to NULL.

This was done in some places, but not all. This is only an issue if
overlay support is enabled and the bitmap clipping is used.

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-vid-cap.c

index c9eb28b..99139a8 100644 (file)
@@ -452,6 +452,12 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
        tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
        dev->crop_cap = dev->src_rect;
        dev->crop_bounds_cap = dev->src_rect;
+       if (dev->bitmap_cap &&
+           (dev->compose_cap.width != dev->crop_cap.width ||
+            dev->compose_cap.height != dev->crop_cap.height)) {
+               vfree(dev->bitmap_cap);
+               dev->bitmap_cap = NULL;
+       }
        dev->compose_cap = dev->crop_cap;
        if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
                dev->compose_cap.height /= 2;
@@ -909,6 +915,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
        struct vivid_dev *dev = video_drvdata(file);
        struct v4l2_rect *crop = &dev->crop_cap;
        struct v4l2_rect *compose = &dev->compose_cap;
+       unsigned orig_compose_w = compose->width;
+       unsigned orig_compose_h = compose->height;
        unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
        int ret;
 
@@ -1025,17 +1033,17 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
                        s->r.height /= factor;
                }
                v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
-               if (dev->bitmap_cap && (compose->width != s->r.width ||
-                                       compose->height != s->r.height)) {
-                       vfree(dev->bitmap_cap);
-                       dev->bitmap_cap = NULL;
-               }
                *compose = s->r;
                break;
        default:
                return -EINVAL;
        }
 
+       if (dev->bitmap_cap && (compose->width != orig_compose_w ||
+                               compose->height != orig_compose_h)) {
+               vfree(dev->bitmap_cap);
+               dev->bitmap_cap = NULL;
+       }
        tpg_s_crop_compose(&dev->tpg, crop, compose);
        return 0;
 }