drm/fbdev-generic: prohibit potential out-of-bounds access
authorjsg <jsg@openbsd.org>
Thu, 15 Jun 2023 02:33:23 +0000 (02:33 +0000)
committerjsg <jsg@openbsd.org>
Thu, 15 Jun 2023 02:33:23 +0000 (02:33 +0000)
From Sui Jingfeng
efd2821b8abeccb6b51423002e2a62921481a26e in linux-6.1.y/6.1.30
c8687694bb1f5c48134f152f8c5c2e53483eb99d in mainline linux

sys/dev/pci/drm/drm_fb_helper.c

index b86d690..449ee16 100644 (file)
@@ -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);