Message ID | 20220621104617.8817-1-tzimmermann@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/fb-helper: Fix out-of-bounds access | expand |
Hello Thomas, On 6/21/22 12:46, Thomas Zimmermann wrote: > Clip memory range to screen-buffer size to avoid out-of-bounds access > in fbdev deferred I/O's damage handling. > > Fbdev's deferred I/O can only track pages. From the range of pages, the > damage handler computes the clipping rectangle for the display update. > If the fbdev screen buffer ends near the beginning of a page, that page > could contain more scanlines. The damage handler would then track these > non-existing scanlines as dirty and provoke an out-of-bounds access > during the screen update. Hence, clip the maximum memory range to the > size of the screen buffer. > > While at it, rename the variables min/max to min_off/max_off in > drm_fb_helper_deferred_io(). This avoids confusion with the macros of > the same name. > > Reported-by: Nuno Gonçalves <nunojpg@gmail.com> > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Tested-by: Nuno Gonçalves <nunojpg@gmail.com> > Fixes: 67b723f5b742 ("drm/fb-helper: Calculate damaged area in separate helper") > Cc: Thomas Zimmermann <tzimmermann@suse.de> > Cc: Javier Martinez Canillas <javierm@redhat.com> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > Cc: Maxime Ripard <mripard@kernel.org> > Cc: <stable@vger.kernel.org> # v5.18+ > --- This makes sense to me. Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Hi Thomas, On Tue, 21 Jun 2022, Thomas Zimmermann wrote: > Clip memory range to screen-buffer size to avoid out-of-bounds access > in fbdev deferred I/O's damage handling. > > Fbdev's deferred I/O can only track pages. From the range of pages, the > damage handler computes the clipping rectangle for the display update. > If the fbdev screen buffer ends near the beginning of a page, that page > could contain more scanlines. The damage handler would then track these > non-existing scanlines as dirty and provoke an out-of-bounds access > during the screen update. Hence, clip the maximum memory range to the > size of the screen buffer. > > While at it, rename the variables min/max to min_off/max_off in > drm_fb_helper_deferred_io(). This avoids confusion with the macros of > the same name. > > Reported-by: Nuno Gonçalves <nunojpg@gmail.com> > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Tested-by: Nuno Gonçalves <nunojpg@gmail.com> > Fixes: 67b723f5b742 ("drm/fb-helper: Calculate damaged area in separate helper") Thanks for your patch, which is now commit ae25885bdf59fde4 ("drm/fb-helper: Fix out-of-bounds access") in drm-misc/for-linux-next. I had seen the crash before, but thought it was a bug in my wip atari-drm driver. When diving deeper today, and consequently looking for recent changes to the damage helper, I found this commit in linux-next. With your patch instead of my own workaround I used this morning, [1] still works fine, so: Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>. Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>. [1] [PATCH] drm/fb-helper: Remove helpers to change frame buffer config https://lore.kernel.org/all/20220629105658.1373770-1-geert@linux-m68k.org Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Hi Am 29.06.22 um 20:17 schrieb Geert Uytterhoeven: > Hi Thomas, > > On Tue, 21 Jun 2022, Thomas Zimmermann wrote: >> Clip memory range to screen-buffer size to avoid out-of-bounds access >> in fbdev deferred I/O's damage handling. >> >> Fbdev's deferred I/O can only track pages. From the range of pages, the >> damage handler computes the clipping rectangle for the display update. >> If the fbdev screen buffer ends near the beginning of a page, that page >> could contain more scanlines. The damage handler would then track these >> non-existing scanlines as dirty and provoke an out-of-bounds access >> during the screen update. Hence, clip the maximum memory range to the >> size of the screen buffer. >> >> While at it, rename the variables min/max to min_off/max_off in >> drm_fb_helper_deferred_io(). This avoids confusion with the macros of >> the same name. >> >> Reported-by: Nuno Gonçalves <nunojpg@gmail.com> >> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> >> Tested-by: Nuno Gonçalves <nunojpg@gmail.com> >> Fixes: 67b723f5b742 ("drm/fb-helper: Calculate damaged area in >> separate helper") > > Thanks for your patch, which is now commit ae25885bdf59fde4 > ("drm/fb-helper: Fix out-of-bounds access") in drm-misc/for-linux-next. > > I had seen the crash before, but thought it was a bug in my wip > atari-drm driver. When diving deeper today, and consequently looking > for recent changes to the damage helper, I found this commit in > linux-next. > > With your patch instead of my own workaround I used this morning, [1] > still works fine, so: > Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>. > Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>. Great thanks a lot. BTW, what's the status of the atari-drm driver? Best regard Thomas > > [1] [PATCH] drm/fb-helper: Remove helpers to change frame buffer config > > https://lore.kernel.org/all/20220629105658.1373770-1-geert@linux-m68k.org > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- > geert@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. > But > when I'm talking to journalists I just say "programmer" or something > like that. > -- Linus Torvalds
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5ad2b6a2778c..1705e8d345ab 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -680,7 +680,11 @@ static void drm_fb_helper_damage(struct fb_info *info, u32 x, u32 y, schedule_work(&helper->damage_work); } -/* Convert memory region into area of scanlines and pixels per scanline */ +/* + * Convert memory region into area of scanlines and pixels per + * scanline. The parameters off and len must not reach beyond + * the end of the framebuffer. + */ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, size_t len, struct drm_rect *clip) { @@ -715,22 +719,29 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, */ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist) { - unsigned long start, end, min, max; + unsigned long start, end, min_off, max_off; struct fb_deferred_io_pageref *pageref; struct drm_rect damage_area; - min = ULONG_MAX; - max = 0; + min_off = ULONG_MAX; + max_off = 0; list_for_each_entry(pageref, pagereflist, list) { start = pageref->offset; end = start + PAGE_SIZE; - min = min(min, start); - max = max(max, end); + min_off = min(min_off, start); + max_off = max(max_off, end); } - if (min >= max) + if (min_off >= max_off) return; - drm_fb_helper_memory_range_to_clip(info, min, max - min, &damage_area); + /* + * As we can only track pages, we might reach beyond the end + * of the screen and account for non-existing scanlines. Hence, + * keep the covered memory area within the screen buffer. + */ + max_off = min(max_off, info->screen_size); + + drm_fb_helper_memory_range_to_clip(info, min_off, max_off - min_off, &damage_area); drm_fb_helper_damage(info, damage_area.x1, damage_area.y1, drm_rect_width(&damage_area), drm_rect_height(&damage_area));