From: Ibrahim Hashimov <security@auditcode.ai>
To: Louis Chauvet <louis.chauvet@bootlin.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>
Cc: Haneen Mohammed <hamohammed.sa@gmail.com>,
Simona Vetter <simona@ffwll.ch>,
Melissa Wen <melissa.srw@gmail.com>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH] drm/vkms: fix vertical stride miscalculation in get_block_step_bytes()
Date: Thu, 9 Jul 2026 00:38:40 +0200 [thread overview]
Message-ID: <20260708223840.973-1-security@auditcode.ai> (raw)
get_block_step_bytes() computes the byte distance between two
vertically adjacent pixel blocks for the READ_TOP_TO_BOTTOM and
READ_BOTTOM_TO_TOP directions as:
pitch * drm_format_info_block_width(fb->format, plane_index)
This is wrong: the vertical distance between two rows of blocks is
the block *pitch*, i.e. pitch multiplied by the block *height*, not
the block width. This is exactly how packed_pixels_offset() computes
it a few lines above in the same file:
int block_pitch = fb->pitches[plane_index] *
drm_format_info_block_height(format, plane_index);
For 1x1-block formats (block_width == block_height == 1) the two
expressions happen to coincide, which is why the bug went unnoticed
for regular formats. Packed sub-byte formats break the assumption:
DRM_FORMAT_R1 has block_width == 8 and block_height == 1, so the
vertical step computed by get_block_step_bytes() is 8x too large.
This over-large step is consumed verbatim by Rx_read_line(), which
advances src_pixels by `step` once per output row without ever
re-validating the result against the framebuffer object bounds
(those bounds were only checked assuming a correct, 1x, step):
src_pixels += step;
so reading a plane in the vertical direction (READ_TOP_TO_BOTTOM /
READ_BOTTOM_TO_TOP, reached via a plane rotation of 90 or 270
degrees) walks off the end of the source buffer object after very
few rows and over-reads adjacent kernel memory (an
out-of-bounds read, not a write). With DRM_FORMAT_R1 and a
writeback connector attached, this is reachable by a local process
that holds DRM master on a loaded vkms device (composition happens
synchronously in vkms_composer_worker()).
Fix get_block_step_bytes() to use drm_format_info_block_height()
for the vertical directions, which matches packed_pixels_offset()
and restores the invariant that the vertical step is exactly one
row of blocks.
Runtime-verified on a v6.19 KASAN (KASAN_VMALLOC) stand: before
this fix, a writeback commit on a rotated DRM_FORMAT_R1 plane
reliably tripped a KASAN-attributed out-of-bounds-read page fault
in Rx_read_line() during vkms_composer_worker(); with this fix
applied, the identical reproducer completes cleanly with no fault
and no KASAN report.
Fixes: b52fd27356af ("drm/vkms: Introduce pixel_read_direction enum")
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Assisted-by: AuditCode-AI:2026.07
---
drivers/gpu/drm/vkms/vkms_formats.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c
index dfb8e13cba87..1e3a6af9cea5 100644
--- a/drivers/gpu/drm/vkms/vkms_formats.c
+++ b/drivers/gpu/drm/vkms/vkms_formats.c
@@ -103,11 +103,11 @@ static int get_block_step_bytes(struct drm_framebuffer *fb, enum pixel_read_dire
case READ_RIGHT_TO_LEFT:
return -fb->format->char_per_block[plane_index];
case READ_TOP_TO_BOTTOM:
- return (int)fb->pitches[plane_index] * drm_format_info_block_width(fb->format,
- plane_index);
- case READ_BOTTOM_TO_TOP:
- return -(int)fb->pitches[plane_index] * drm_format_info_block_width(fb->format,
+ return (int)fb->pitches[plane_index] * drm_format_info_block_height(fb->format,
plane_index);
+ case READ_BOTTOM_TO_TOP:
+ return -(int)fb->pitches[plane_index] * drm_format_info_block_height(fb->format,
+ plane_index);
}
return 0;
--
2.50.1 (Apple Git-155)
reply other threads:[~2026-07-08 22:39 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260708223840.973-1-security@auditcode.ai \
--to=security@auditcode.ai \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=hamohammed.sa@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=louis.chauvet@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=melissa.srw@gmail.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=stable@vger.kernel.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox