linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fbdev: core: Fix vmalloc-out-of-bounds in fb_imageblit
@ 2025-11-19 13:38 ssrane_b23
  2025-11-19 21:05 ` Kajtár Zsolt
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: ssrane_b23 @ 2025-11-19 13:38 UTC (permalink / raw)
  To: Zsolt Kajtar, Simona Vetter, Helge Deller
  Cc: Shaurya Rane, linux-fbdev, dri-devel, linux-kernel,
	syzbot+5a40432dfe8f86ee657a

From: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>

syzbot reported a vmalloc-out-of-bounds write in fb_imageblit. The crash
occurs when drawing an image at the very end of the framebuffer memory.

The current bounds check in fb_imageblit limits the drawing height (max_y)
by dividing the screen size by the line length. However, this calculation
only ensures that the start of the last line fits within the buffer. It
fails to account for the width of the image on that final line. If the
image width (multiplied by bpp) exceeds the remaining space on the last
line, the drawing routine writes past the end of the allocated video
memory.

This patch replaces the insufficient check with a more precise one. It
calculates the effective width in bytes of the image (accounting for
clipping against xres_virtual) and ensures that the last byte of the
operation falls within the screen buffer. Specifically, it checks if
'(dy + height - 1) * line_length + effective_width_bytes' exceeds
screen_size. If it does, the drawing height max_y is reduced to
prevent the out-of-bounds access.

Reported-by: syzbot+5a40432dfe8f86ee657a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5a40432dfe8f86ee657a

Signed-off-by: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>
---
 drivers/video/fbdev/core/fb_imageblit.h | 66 +++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 4 deletions(-)

diff --git a/drivers/video/fbdev/core/fb_imageblit.h b/drivers/video/fbdev/core/fb_imageblit.h
index 3b2bb4946505..0c0d05cff3f8 100644
--- a/drivers/video/fbdev/core/fb_imageblit.h
+++ b/drivers/video/fbdev/core/fb_imageblit.h
@@ -485,11 +485,69 @@ static inline void fb_imageblit(struct fb_info *p, const struct fb_image *image)
 	struct fb_address dst = fb_address_init(p);
 	struct fb_reverse reverse = fb_reverse_init(p);
 	const u32 *palette = fb_palette(p);
+	struct fb_image clipped_image;
+	u32 max_x, max_y;
+	unsigned long max_offset_bytes;
+
+	/* Validate basic parameters */
+	if (!image || !p->screen_buffer || !p->screen_size ||
+	    !image->width || !image->height)
+		return;
+
+	/* Calculate maximum addressable coordinates based on virtual resolution and buffer size */
+	max_x = p->var.xres_virtual;
+	max_y = p->var.yres_virtual;
+
+	/* Check against actual buffer size to prevent vmalloc overflow */
+	{
+		unsigned long effective_width_bytes;
+		u32 right_edge = image->dx + image->width;
+
+		if (right_edge < image->dx)
+			right_edge = max_x;
+		else
+			right_edge = min(right_edge, max_x);
+
+		effective_width_bytes = (unsigned long)right_edge * bpp;
+		effective_width_bytes = (effective_width_bytes + 7) / 8;
+
+		if (effective_width_bytes > p->screen_size) {
+			max_y = 0;
+		} else if (p->fix.line_length) {
+			u32 max_lines = (p->screen_size - effective_width_bytes) /
+					p->fix.line_length + 1;
+			if (max_lines < max_y)
+				max_y = max_lines;
+		}
+	}
+
+	/* If image is completely outside bounds, skip it */
+	if (image->dx >= max_x || image->dy >= max_y)
+		return;
+
+	/* Create clipped image - clip to virtual resolution bounds */
+	clipped_image = *image;
+
+	/* Clip width if it extends beyond right edge */
+	if (clipped_image.dx + clipped_image.width > max_x) {
+		if (clipped_image.dx < max_x)
+			clipped_image.width = max_x - clipped_image.dx;
+		else
+			return; /* completely outside */
+	}
+
+	/* Clip height if it extends beyond bottom edge */
+	if (clipped_image.dy + clipped_image.height > max_y) {
+		if (clipped_image.dy < max_y)
+			clipped_image.height = max_y - clipped_image.dy;
+		else
+			return; /* completely outside */
+	}
 
-	fb_address_forward(&dst, image->dy * bits_per_line + image->dx * bpp);
+	fb_address_forward(&dst, clipped_image.dy * bits_per_line + clipped_image.dx * bpp);
 
-	if (image->depth == 1)
-		fb_bitmap_imageblit(image, &dst, bits_per_line, palette, bpp, reverse);
+	if (clipped_image.depth == 1)
+		fb_bitmap_imageblit(&clipped_image, &dst, bits_per_line, palette, bpp, reverse);
 	else
-		fb_color_imageblit(image, &dst, bits_per_line, palette, bpp, reverse);
+		fb_color_imageblit(&clipped_image, &dst, bits_per_line, palette, bpp, reverse);
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-11-26  6:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-19 13:38 [PATCH] fbdev: core: Fix vmalloc-out-of-bounds in fb_imageblit ssrane_b23
2025-11-19 21:05 ` Kajtár Zsolt
2025-11-20  9:23 ` kernel test robot
2025-11-26  6:55 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).