On Sat Sep 5 18:58:18 2026 +0300, Maxim Skokov wrote:
> syzbot reports a vmalloc out-of-bounds write in the test pattern
> generator:
> 
> BUG: KASAN: vmalloc-out-of-bounds in tpg_fill_plane_pattern 
> drivers/media/common/v4l2-tpg/v4l2-tpg-core.c:2617 [inline]
> BUG: KASAN: vmalloc-out-of-bounds in tpg_fill_plane_buffer+0x2063/0x4160 
> drivers/media/common/v4l2-tpg/v4l2-tpg-core.c:2705
> Write of size 720 at addr ffffc900038f9d50 by task vivid-000-vid-c/6017
> 
> The reproducer requests a 720x49 NV12 capture format, i.e. an odd
> height for a format whose chroma plane is vertically subsampled.
> 
> The buffer size is derived from the height by a truncating division:
> 
>         sizes[p] = (tpg_g_line_width(&dev->tpg, p) * h) /
>                    dev->fmt_cap->vdownsampling[p] +
>                    dev->fmt_cap->data_offset[p];
> 
> For a single buffer holding both planes tpg_g_line_width() returns
> 720 + 720 / 2 = 1080, so 1080 * 49 = 52920 bytes get allocated.
> 
> tpg_fill_plane_buffer() however emits one chroma line for every two
> luma lines, i.e. DIV_ROUND_UP(49, 2) = 25 lines, and thus needs
> 49 * 720 + 25 * 720 = 53280 bytes. The memcpy() of the last chroma
> line runs 360 bytes past the end of the buffer.
> 
> An odd height is not meaningful for a 4:2:0 format in the first place,
> since the chroma plane would have to hold half a line. Rather than
> fixing up each of the ~10 sites that divide the height by
> vdownsampling[], round the height down to a multiple of the vertical
> subsampling factor where it enters the driver. Adjusting the format is
> what TRY_FMT/S_FMT are for, and it keeps every later division exact.
> 
> Formats without vertical subsampling are unaffected and keep accepting
> odd heights.
> 
> Tested with the syzbot reproducer, which no longer triggers the splat,
> and by streaming NV12, NV21, YUV420, YVU420 and YUYV at heights 47,
> 48, 49, 51, 480, 481 and 1081. v4l2-compliance gives identical results
> before and after (48 of 50 succeeded on the vivid device in both
> cases; the two failures are pre-existing and unrelated).
> 
> Fixes: ddcaee9dd4c0 ("[media] vivid: add support for single buffer planar 
> formats")
> Cc: [email protected]
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=cb43e758a4dc84dd467f
> Signed-off-by: Maxim Skokov <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/test-drivers/vivid/vivid-vid-cap.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

---

diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c 
b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
index e20449084709..147af0f9b077 100644
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
@@ -570,6 +570,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
        const struct vivid_fmt *fmt;
        unsigned bytesperline, max_bpl;
        unsigned factor = 1;
+       unsigned int vdiv = 1;
        unsigned w, h;
        unsigned p;
        bool user_set_csc = !!(mp->flags & V4L2_PIX_FMT_FLAG_SET_CSC);
@@ -622,6 +623,18 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
                mp->height = r.height / factor;
        }
 
+       /*
+        * The chroma planes of vertically subsampled formats hold
+        * height / vdownsampling lines. If the height is not a multiple of
+        * the subsampling factor, then the buffer size calculations round
+        * that number down while the test pattern generator rounds it up,
+        * so the generator writes one line past the end of the buffer.
+        * Round the height down to keep both in sync.
+        */
+       for (p = 0; p < fmt->planes; p++)
+               vdiv = max(vdiv, fmt->vdownsampling[p]);
+       mp->height = rounddown(mp->height, vdiv);
+
        /* This driver supports custom bytesperline values */
 
        mp->num_planes = fmt->buffers;
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to