syzbot.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Slawomir Stepien <sst@poczta.fm>
To: syzbot <syzbot@kernel.org>
Cc: syzkaller-upstream-moderation@googlegroups.com, syzbot@lists.linux.dev
Subject: Re: [PATCH RFC] drm/cirrus-qemu: Use actual VRAM size to prevent out-of-bounds write
Date: Mon, 24 Aug 2026 13:58:44 +0200	[thread overview]
Message-ID: <aowx9LUZgrhDZnSM@nr200> (raw)
In-Reply-To: <6e0e7e49-c50d-472e-9cc2-ceaf814e0fc7@mail.kernel.org>

On sie 16, 2026 23:42, 'syzbot' via syzkaller-upstream-moderation wrote:
> 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)

How about checking here also if the returned value is == to CIRRUS_VRAM_SIZE and leave the
CIRRUS_VRAM_SIZE as it is right now? Or even better:

if (pci_resource_len(pdev, 0) != CIRRUS_VRAM_SIZE)
	return -ENODEV;

This will make this change a much simpler one!

It seems, after checking the qemu sources, that CLGD5446 must have 4MB and there is not other
option.

> +		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

-- 
Slawomir Stepien

      reply	other threads:[~2026-08-24 11:58 UTC|newest]

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

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=aowx9LUZgrhDZnSM@nr200 \
    --to=sst@poczta.fm \
    --cc=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).