lkml.org 
[lkml]   [2022]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.19 0086/1157] drm/fb-helper: Fix out-of-bounds access
    Date
    From: Thomas Zimmermann <tzimmermann@suse.de>

    commit ae25885bdf59fde40726863c57fd20e4a0642183 upstream.

    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>
    Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
    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+
    Link: https://patchwork.freedesktop.org/patch/msgid/20220621104617.8817-1-tzimmermann@suse.de
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/gpu/drm/drm_fb_helper.c | 27 +++++++++++++++++++--------
    1 file changed, 19 insertions(+), 8 deletions(-)

    --- 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
    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_t
    */
    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));

    \
     
     \ /
      Last update: 2022-08-16 00:23    [W:3.618 / U:0.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site