⬢ DragonFlyBSD Kernel Audit
DF-4974 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/radeon_cursor.c b/sys/dev/drm/radeon/radeon_cursor.c
index 1111111..2222222 100644
--- a/sys/dev/drm/radeon/radeon_cursor.c
+++ b/sys/dev/drm/radeon/radeon_cursor.c
@@ -307,6 +307,18 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
 		return -ENOENT;
 	}
 
+	/*
+	 * The display engine fetches width*height*4 bytes starting at the
+	 * pinned cursor BO's VRAM address (pre-AVIVO adds up to
+	 * (max_cursor_height - 1) * 256 more via CUR_OFFSET).  Require the
+	 * BO to cover the maximum fetch window, otherwise the cursor scanout
+	 * reads past the end of the BO and paints adjacent VRAM contents on
+	 * the screen.
+	 */
+	if (radeon_bo_size(gem_to_radeon_bo(obj)) <
+	    (u64)radeon_crtc->max_cursor_width *
+			  radeon_crtc->max_cursor_height * 4) {
+		DRM_ERROR("Cursor BO too small for %d x %d cursor\n",
+			  radeon_crtc->max_cursor_width,
+			  radeon_crtc->max_cursor_height);
+		drm_gem_object_put_unlocked(obj);
+		return -EINVAL;
+	}
+
 	robj = gem_to_radeon_bo(obj);
 	ret = radeon_bo_reserve(robj, false);
 	if (ret != 0) {