dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Aldo Ariel Panzardo" <qwe.aldo@gmail.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2 3/4] drm/qxl: reject relocations whose writes cross a page boundary
Date: Sun, 13 Sep 2026 22:45:36 +0000	[thread overview]
Message-ID: <20260913224536.E09AF1F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260913223000.695299-4-qwe.aldo@gmail.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] An integer overflow in `reloc.dst_offset + write_size` bypasses bounds checks, leading to out-of-bounds writes within the shared command buffer.
- [Critical] The fallback path in `qxl_bo_kmap_atomic_page` improperly multiplies an already byte-scaled offset by `PAGE_SIZE`, leading to massive out-of-bounds kernel memory corruption.
- [High] Type truncation of `dst_offset` and passing an unsigned value to a signed `int` causes negative memory mapping before the VRAM buffer.
- [High] `qxl_bo_kmap_atomic_page` fails to increment `map_count` in the fallback path when `bo->kptr` is already set, causing a reference count underflow when unmapped.
--

commit 9e6139abca50852ee6ddcc5adb21b30da6e7a5ae
Author: Aldo Ariel Panzardo <qwe.aldo@gmail.com>

drm/qxl: reject relocations whose writes cross a page boundary

This commit adds a check to reject relocations in the qxl driver where the
write would cross a page boundary, preventing out-of-bounds writes into the
kernel's fixmap area.

> diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
> index e727a35c94136..9fba6e26d048b 100644
> --- a/drivers/gpu/drm/qxl/qxl_ioctl.c
> +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
[ ... ]
> @@ -247,6 +247,12 @@ static int qxl_process_single_command(struct qxl_device *qdev,
[ ... ]
>  		if (reloc.dst_handle) {
>  			ret = qxlhw_handle_to_bo(file_priv, reloc.dst_handle, release,
>  						 &reloc_info[i].dst_bo);
>  			if (ret)
>  				goto out_free_bos;
>  			reloc_info[i].dst_offset = reloc.dst_offset;
>  		} else {
>  			if (reloc.dst_offset < sizeof(union qxl_release_info) ||
>  			    reloc.dst_offset + write_size >
>  			    sizeof(union qxl_release_info) + cmd->command_size) {
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: Critical]
This isn't a bug introduced by this patch, but does the addition
reloc.dst_offset + write_size overflow?

If a user sets reloc.dst_offset to a value like 0xFFFFFFFFFFFFFFF8 (-8),
the addition of write_size (8) would wrap around to 0. Since the first check
(0xFFFFFFFFFFFFFFF8 < 40) is false, and the second check (0 > 40 +
cmd->command_size) is also false, the bounds checks are bypassed.

This could allow out-of-bounds writes into the shared cmd_bo ring buffer.

>  				ret = -EINVAL;
>  				goto out_free_bos;
>  			}
>  			reloc_info[i].dst_bo = cmd_bo;
>  			reloc_info[i].dst_offset = reloc.dst_offset + release->release_offset;
>  		}
> 
>  		if ((u64)reloc_info[i].dst_offset + write_size >
>  		    reloc_info[i].dst_bo->tbo.base.size) {
>  			ret = -EINVAL;
>  			goto out_free_bos;
>  		}
> 
> +		if ((reloc_info[i].dst_offset & ~PAGE_MASK) + write_size >
> +		    PAGE_SIZE) {
> +			ret = -EINVAL;
> +			goto out_free_bos;
> +		}
> +
>  		/* reserve and validate the reloc dst bo */


While reviewing the relocation bounds checks, I noticed a few pre-existing
issues in the page mapping code called during relocations:

drivers/gpu/drm/qxl/qxl_object.c:qxl_bo_kmap_atomic_page() {
    ...
	offset = bo->tbo.resource->start << PAGE_SHIFT;
	return io_mapping_map_atomic_wc(map, offset + page_offset);
}

[Severity: High]
This isn't a bug introduced by this patch, but is it safe to pass page_offset
as a signed int?

The callers pass dst_offset & PAGE_MASK to qxl_bo_kmap_atomic_page(). If a
user provides a large offset like 0x80000000 for a large buffer, it will be
interpreted as a negative integer (-2147483648) and sign-extended in
io_mapping_map_atomic_wc(), mapping memory before the intended physical VRAM
buffer.


drivers/gpu/drm/qxl/qxl_object.c:qxl_bo_kmap_atomic_page() {
    ...
fallback:
	if (bo->kptr) {
		rptr = bo->kptr + (page_offset * PAGE_SIZE);
		return rptr;
	}

	ret = qxl_bo_vmap_locked(bo, &bo_map);
	if (ret)
		return NULL;
	rptr = bo_map.vaddr;

	rptr += page_offset * PAGE_SIZE;
	return rptr;
}

[Severity: Critical]
This isn't a bug introduced by this patch, but is page_offset incorrectly
multiplied by PAGE_SIZE here?

The callers already pass a byte-scaled offset (e.g., info->dst_offset &
PAGE_MASK) as the page_offset argument. If the fallback path is taken
(e.g. for a buffer in TTM_PL_SYSTEM), multiplying this byte offset by
PAGE_SIZE again causes a massive out-of-bounds kernel pointer calculation.


[Severity: High]
This isn't a bug introduced by this patch, but does the fallback path fail
to update the map count when bo->kptr is already set?

drivers/gpu/drm/qxl/qxl_object.c:qxl_bo_kmap_atomic_page() {
    ...
fallback:
	if (bo->kptr) {
		rptr = bo->kptr + (page_offset * PAGE_SIZE);
		return rptr;
	}
    ...
}

If a buffer is already mapped via the fallback path (for instance, exported
via PRIME and vmapped by another driver), returning bo->kptr without
incrementing map_count creates a mismatch.

When it is later unmapped:

drivers/gpu/drm/qxl/qxl_object.c:qxl_bo_kunmap_atomic_page() {
    ...
 fallback:
	qxl_bo_vunmap_locked(bo);
}

The qxl_bo_vunmap_locked() function unconditionally decrements map_count to 0,
prematurely unmapping the buffer while the original map user is still active.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260913223000.695299-1-qwe.aldo@gmail.com?part=3

  reply	other threads:[~2026-09-13 22:45 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-13 22:29 [PATCH v2 0/4] drm/qxl: fix multiple missing bounds checks in execbuffer relocations Aldo Ariel Panzardo
2026-09-13 22:29 ` [PATCH v2 1/4] drm/qxl: validate relocation dst_offset against destination BO Aldo Ariel Panzardo
2026-09-13 22:44   ` sashiko-bot
2026-09-13 22:29 ` [PATCH v2 2/4] drm/qxl: reject command sizes that exceed the release slot Aldo Ariel Panzardo
2026-09-13 22:45   ` sashiko-bot
2026-09-13 22:29 ` [PATCH v2 3/4] drm/qxl: reject relocations whose writes cross a page boundary Aldo Ariel Panzardo
2026-09-13 22:45   ` sashiko-bot [this message]
2026-09-13 22:30 ` [PATCH v2 4/4] drm/qxl: validate relocation src_offset and fix type truncation Aldo Ariel Panzardo
2026-09-13 22:46   ` sashiko-bot

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=20260913224536.E09AF1F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=qwe.aldo@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /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