Commit af22d6a8 authored by Hamza Mahfooz's avatar Hamza Mahfooz Committed by Alex Deucher
Browse files

drm/amd/display: perform a bounds check before filling dirty rectangles



Currently, it is possible for us to access memory that we shouldn't.
Since, we acquire (possibly dangling) pointers to dirty rectangles
before doing a bounds check to make sure we can actually accommodate the
number of dirty rectangles userspace has requested to fill. This issue
is especially evident if a compositor requests both MPO and damage clips
at the same time, in which case I have observed a soft-hang. So, to
avoid this issue, perform the bounds check before filling a single dirty
rectangle and WARN() about it, if it is ever attempted in
fill_dc_dirty_rect().

Cc: stable@vger.kernel.org # 6.1+
Fixes: 30ebe415 ("drm/amd/display: add FB_DAMAGE_CLIPS support")
Reviewed-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8ef84c1a
Loading
Loading
Loading
Loading
+4 −9
Original line number Diff line number Diff line
@@ -5063,11 +5063,7 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
				      s32 y, s32 width, s32 height,
				      int *i, bool ffu)
{
	if (*i > DC_MAX_DIRTY_RECTS)
		return;

	if (*i == DC_MAX_DIRTY_RECTS)
		goto out;
	WARN_ON(*i >= DC_MAX_DIRTY_RECTS);

	dirty_rect->x = x;
	dirty_rect->y = y;
@@ -5083,7 +5079,6 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
			"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
			plane->base.id, x, y, width, height);

out:
	(*i)++;
}

@@ -5170,6 +5165,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,

	*dirty_regions_changed = bb_changed;

	if ((num_clips + (bb_changed ? 2 : 0)) > DC_MAX_DIRTY_RECTS)
		goto ffu;

	if (bb_changed) {
		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
				   new_plane_state->crtc_x,
@@ -5199,9 +5197,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
				   new_plane_state->crtc_h, &i, false);
	}

	if (i > DC_MAX_DIRTY_RECTS)
		goto ffu;

	flip_addrs->dirty_rect_count = i;
	return;