summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2023-06-15 02:33:24 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2023-06-15 02:33:24 +0000
commit9b30049a7cd357a4b12c1e98ada7121c9a36f5ae (patch)
tree64e81bbb0e55accd6f9582f59e746802e9281fd0
parent4f73b047957a1a93de70e729d0c0b290f6dd1c8a (diff)
drm/fbdev-generic: prohibit potential out-of-bounds access
From Sui Jingfeng efd2821b8abeccb6b51423002e2a62921481a26e in linux-6.1.y/6.1.30 c8687694bb1f5c48134f152f8c5c2e53483eb99d in mainline linux
-rw-r--r--sys/dev/pci/drm/drm_fb_helper.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/dev/pci/drm/drm_fb_helper.c b/sys/dev/pci/drm/drm_fb_helper.c
index b86d690e2a6..449ee168a8d 100644
--- a/sys/dev/pci/drm/drm_fb_helper.c
+++ b/sys/dev/pci/drm/drm_fb_helper.c
@@ -724,19 +724,27 @@ static void drm_fb_helper_damage(struct fb_info *info, u32 x, u32 y,
static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, size_t len,
struct drm_rect *clip)
{
+ u32 line_length = info->fix.line_length;
+ u32 fb_height = info->var.yres;
off_t end = off + len;
u32 x1 = 0;
- u32 y1 = off / info->fix.line_length;
+ u32 y1 = off / line_length;
u32 x2 = info->var.xres;
- u32 y2 = DIV_ROUND_UP(end, info->fix.line_length);
+ u32 y2 = DIV_ROUND_UP(end, line_length);
+
+ /* Don't allow any of them beyond the bottom bound of display area */
+ if (y1 > fb_height)
+ y1 = fb_height;
+ if (y2 > fb_height)
+ y2 = fb_height;
if ((y2 - y1) == 1) {
/*
* We've only written to a single scanline. Try to reduce
* the number of horizontal pixels that need an update.
*/
- off_t bit_off = (off % info->fix.line_length) * 8;
- off_t bit_end = (end % info->fix.line_length) * 8;
+ off_t bit_off = (off % line_length) * 8;
+ off_t bit_end = (end % line_length) * 8;
x1 = bit_off / info->var.bits_per_pixel;
x2 = DIV_ROUND_UP(bit_end, info->var.bits_per_pixel);