summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2025-03-28 10:17:06 +0100
committerThomas Zimmermann <tzimmermann@suse.de>2025-04-01 15:35:12 +0200
commit1eb4d744fb86199f0f6da9463d83ed3eec2f61bf (patch)
treec06aca14c80c75a4797a1490e77f5db384bb536e
parent4bfb389a0136a13f0802eeb5e97a0e76d88f77ae (diff)
drm/cirrus-qemu: Stricter mode validation
Implement strict checking of a display mode's minimum scanline pitch in cirrus_mode_config_mode_valid(). Sort out all modes that possibly overflow the maximum pitch. The current validation only tests against a display mode's minimum requirements for video memory. Only atomic_check later tests against the pitch limit before programming the framebuffer. The problem is that user-space compositors do not handle this gracefully. If atomic_check fails to validate the scanline pitch and returns an error, the compositor, namely Weston, does nothing and the display remains stale. Ruling out display modes that possibly overflow the pitch avoids this problem. With only 4 MiB of video memory available, this effectively limits horizontal resolution to 800 pixels. But with cirrus-qemu being low-end and obsolete, this is probably not an issue in practice. Better alternatives are available in qemu. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Link: https://lore.kernel.org/r/20250328091821.195061-3-tzimmermann@suse.de
-rw-r--r--drivers/gpu/drm/tiny/cirrus-qemu.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/gpu/drm/tiny/cirrus-qemu.c b/drivers/gpu/drm/tiny/cirrus-qemu.c
index a00d3b7ded6c..0306433ec117 100644
--- a/drivers/gpu/drm/tiny/cirrus-qemu.c
+++ b/drivers/gpu/drm/tiny/cirrus-qemu.c
@@ -613,9 +613,17 @@ static enum drm_mode_status cirrus_mode_config_mode_valid(struct drm_device *dev
const struct drm_display_mode *mode)
{
const struct drm_format_info *format = drm_format_info(DRM_FORMAT_XRGB8888);
- uint64_t pitch = drm_format_info_min_pitch(format, 0, mode->hdisplay);
+ u64 pitch;
- if (pitch * mode->vdisplay > CIRRUS_VRAM_SIZE)
+ if (drm_WARN_ON_ONCE(dev, !format))
+ return MODE_ERROR; /* driver bug */
+
+ pitch = drm_format_info_min_pitch(format, 0, mode->hdisplay);
+ if (!pitch)
+ return MODE_BAD_WIDTH;
+ if (pitch > CIRRUS_MAX_PITCH)
+ return MODE_BAD_WIDTH; /* maximum programmable pitch */
+ if (pitch > CIRRUS_VRAM_SIZE / mode->vdisplay)
return MODE_MEM;
return MODE_OK;