[PATCH 3/4] media: vicodec: clamp visible dimensions on S_FMT to coded bounds

Junrui Luo <[email protected]>
Newsgroups org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media,org.kernel.vger.stable
Message-ID <[email protected]>
Setting a smaller CAPTURE format on the stateful decoder lets the visible
dimensions exceed the coded ones, and decode_plane() then writes past the
end of the capture buffer -- a kernel heap out-of-bounds write
controllable from unprivileged userspace.

vidioc_s_fmt() writes coded_width, coded_height and sizeimage but never
touches visible_width or visible_height, which vicodec_open() initialised
to 1280x720, so shrinking the coded pair leaves the visible pair larger.
job_ready() compares the bitstream header against the stale visible
dimensions, so no source-change event fires and decode_plane() iterates
over the visible height at a stride derived from coded_width.

On a KASAN-enabled kernel, a 1280x720 I-frame decoded into a 640x368
CAPTURE buffer triggers:

  BUG: KASAN: vmalloc-out-of-bounds in decode_plane+0x1bb8/0x34b0
  Write of size 1 at addr ffffc900004b8080 by task trigger_bin/69

  Call Trace:
   decode_plane+0x1bb8/0x34b0
   fwht_decode_frame+0x173/0x620
   v4l2_fwht_decode+0x595/0xea0

Clamp visible_width and visible_height to the new coded bounds after
every S_FMT, maintaining the invariant visible <= coded that
update_capture_data_from_header() relies on.

Fixes: 3b15f68e19c2 ("media: vicodec: Add support for resolution change event.")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
 drivers/media/test-drivers/vicodec/vicodec-core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c
index 318e8330f16a..36b92f68ac42 100644
--- a/drivers/media/test-drivers/vicodec/vicodec-core.c
+++ b/drivers/media/test-drivers/vicodec/vicodec-core.c
@@ -1029,6 +1029,11 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
 		return -EINVAL;
 	}
 
+	q_data->visible_width = min(q_data->visible_width,
+				    q_data->coded_width);
+	q_data->visible_height = min(q_data->visible_height,
+				     q_data->coded_height);
+
 	dprintk(ctx->dev,
 		"Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
 		f->type, q_data->coded_width, q_data->coded_height,

-- 
2.51.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.