All of lore.kernel.org
 help / color / mirror / Atom feed
From: "syzbot" <syzbot@kernel.org>
To: syzkaller-upstream-moderation@googlegroups.com
Cc: syzbot@lists.linux.dev
Subject: [PATCH RFC] drm/cirrus-qemu: Use actual VRAM size to prevent out-of-bounds write
Date: Sun, 16 Aug 2026 23:42:35 +0000 (UTC)	[thread overview]
Message-ID: <6e0e7e49-c50d-472e-9cc2-ceaf814e0fc7@mail.kernel.org> (raw)

The `cirrus-qemu` driver previously relied on a hardcoded constant
`CIRRUS_VRAM_SIZE` (4 MB) to validate framebuffer sizes. However, during
device probe, the driver maps the VRAM using the actual size of the PCI
device's BAR0.

If a privileged user unbinds a random PCI device with a BAR0 smaller than 4
MB and binds the `cirrus-qemu` driver to it, the mapped VRAM will be
smaller than 4 MB. Because the validation checks still used the hardcoded 4
MB size, the driver would allow the creation of a framebuffer larger than
the actually mapped VRAM.

When the DRM device is closed, `drm_release()` triggers a full atomic
commit to restore the fbdev mode. This calls
`cirrus_primary_plane_helper_atomic_update()`, which uses `drm_fb_memcpy()`
to copy the framebuffer into the mapped VRAM. Since the mapped VRAM is
smaller than the framebuffer, `memcpy_toio()` writes past the end of the
mapped I/O memory, resulting in a supervisor write page fault:

BUG: unable to handle page fault for address: ffffc900033dd000
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
...
RIP: 0010:rep_movs arch/x86/lib/iomem.c:13 [inline]
RIP: 0010:string_memcpy_toio arch/x86/lib/iomem.c:64 [inline]
RIP: 0010:memcpy_toio+0x7c/0xe0 arch/x86/lib/iomem.c:110
...
Call Trace:
 <TASK>
 iosys_map_memcpy_to include/linux/iosys-map.h:285 [inline]
 drm_fb_memcpy+0x325/0x5d0 drivers/gpu/drm/drm_format_helper.c:442
 cirrus_primary_plane_helper_atomic_update+0x98a/0xb00
 drivers/gpu/drm/tiny/cirrus-qemu.c:358
 drm_atomic_helper_commit_planes+0x626/0xea0
 drivers/gpu/drm/drm_atomic_helper.c:3038
 drm_atomic_helper_commit_tail+0x60/0x510
 drivers/gpu/drm/drm_atomic_helper.c:1989
 commit_tail+0x2b1/0x3c0 drivers/gpu/drm/drm_atomic_helper.c:2074
 drm_atomic_helper_commit+0xa77/0xb10
 drivers/gpu/drm/drm_atomic_helper.c:2312
...

To fix this, remove the hardcoded `CIRRUS_VRAM_SIZE` and dynamically track
the actual VRAM size in `struct cirrus_device`. Initialize this size from
the PCI resource length during probe, ensuring it is non-zero. Update the
validation hooks `cirrus_primary_plane_helper_atomic_check()` and
`cirrus_mode_config_mode_valid()` to use the dynamically tracked VRAM size,
ensuring that framebuffers strictly fit within the mapped memory.

Fixes: ab3e023b1b4c ("drm/cirrus: rewrite and modernize driver.")
Assisted-by: Gemini:gemini-3.6-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+2442951a6abb004df963@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=2442951a6abb004df963
Link: https://syzkaller.appspot.com/ai_job?id=0995d2c9-3eea-4945-84e7-ab3d2acd4f21
To: "David Airlie" <airlied@gmail.com>
To: "Dave Airlie" <airlied@redhat.com>
To: <dri-devel@lists.freedesktop.org>
To: "Gerd Hoffmann" <kraxel@redhat.com>
To: "Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>
To: "Maxime Ripard" <mripard@kernel.org>
To: "Simona Vetter" <simona@ffwll.ch>
To: "Thomas Zimmermann" <tzimmermann@suse.de>
To: <virtualization@lists.linux.dev>
Cc: "Jani Nikula" <jani.nikula@intel.com>
Cc: <linux-kernel@vger.kernel.org>
Cc: "Luca Ceresoli" <luca.ceresoli@bootlin.com>

---
diff --git a/drivers/gpu/drm/tiny/cirrus-qemu.c b/drivers/gpu/drm/tiny/cirrus-qemu.c
index 075221b43..7f8cb3264 100644
--- a/drivers/gpu/drm/tiny/cirrus-qemu.c
+++ b/drivers/gpu/drm/tiny/cirrus-qemu.c
@@ -55,7 +55,6 @@
 #define DRIVER_MINOR 0
 
 #define CIRRUS_MAX_PITCH (0x1FF << 3)      /* (4096 - 1) & ~111b bytes */
-#define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
 
 struct cirrus_device {
 	struct drm_device	       dev;
@@ -68,6 +67,7 @@ struct cirrus_device {
 
 	/* HW resources */
 	void __iomem		       *vram;
+	size_t			       vram_size;
 	void __iomem		       *mmio;
 };
 
@@ -298,6 +298,7 @@ static const uint64_t cirrus_primary_plane_format_modifiers[] = {
 static int cirrus_primary_plane_helper_atomic_check(struct drm_plane *plane,
 						    struct drm_atomic_commit *state)
 {
+	struct cirrus_device *cirrus = to_cirrus(plane->dev);
 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
 	struct drm_framebuffer *fb = new_plane_state->fb;
 	struct drm_crtc *new_crtc = new_plane_state->crtc;
@@ -319,7 +320,7 @@ static int cirrus_primary_plane_helper_atomic_check(struct drm_plane *plane,
 	/* validate size constraints */
 	if (fb->pitches[0] > CIRRUS_MAX_PITCH)
 		return -EINVAL;
-	else if (fb->pitches[0] > CIRRUS_VRAM_SIZE / fb->height)
+	else if (fb->pitches[0] > cirrus->vram_size / fb->height)
 		return -EINVAL;
 
 	return 0;
@@ -514,6 +515,7 @@ static int cirrus_pipe_init(struct cirrus_device *cirrus)
 static enum drm_mode_status cirrus_mode_config_mode_valid(struct drm_device *dev,
 							  const struct drm_display_mode *mode)
 {
+	struct cirrus_device *cirrus = to_cirrus(dev);
 	const struct drm_format_info *format = drm_format_info(DRM_FORMAT_XRGB8888);
 	u64 pitch;
 
@@ -525,7 +527,7 @@ static enum drm_mode_status cirrus_mode_config_mode_valid(struct drm_device *dev
 		return MODE_BAD_WIDTH;
 	if (pitch > CIRRUS_MAX_PITCH)
 		return MODE_BAD_WIDTH; /* maximum programmable pitch */
-	if (pitch > CIRRUS_VRAM_SIZE / mode->vdisplay)
+	if (pitch > cirrus->vram_size / mode->vdisplay)
 		return MODE_MEM;
 
 	return MODE_OK;
@@ -602,8 +604,12 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
 
 	dev = &cirrus->dev;
 
+	if (pci_resource_len(pdev, 0) == 0)
+		return -ENODEV;
+
+	cirrus->vram_size = pci_resource_len(pdev, 0);
 	cirrus->vram = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0),
-				    pci_resource_len(pdev, 0));
+				    cirrus->vram_size);
 	if (cirrus->vram == NULL)
 		return -ENOMEM;
 


base-commit: db2ddb87143519e20a95aa36c60b36107b736a58
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.

             reply	other threads:[~2026-08-16 23:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-16 23:42 syzbot [this message]
2026-08-24 11:58 ` [PATCH RFC] drm/cirrus-qemu: Use actual VRAM size to prevent out-of-bounds write Slawomir Stepien

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6e0e7e49-c50d-472e-9cc2-ceaf814e0fc7@mail.kernel.org \
    --to=syzbot@kernel.org \
    --cc=syzbot@lists.linux.dev \
    --cc=syzkaller-upstream-moderation@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.