The Linux Kernel Mailing List
 help / color / mirror / Atom feed
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