All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset
@ 2026-06-10  6:03 Joonas Lahtinen
  2026-06-10  6:14 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Joonas Lahtinen @ 2026-06-10  6:03 UTC (permalink / raw)
  To: Intel graphics driver community testing & development
  Cc: Direct Rendering Infrastructure - Development, Joonas Lahtinen,
	Matthew Wilcox (Oracle), stable, Tvrtko Ursulin, Simona Vetter,
	Jani Nikula, Rodrigo Vivi

sg_page() returns struct page pointer not (void *) so the scaling
of pread/pwrite is wrong for phys BO and wrong parts of BO would be
accessed if non-zero offset is used.

Last impacted platform with overlay or cursor planes using phys
mapping was Gen3/945G/Lakeport.

Reported-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Fixes: c6790dc22312 ("drm/i915: Wean off drm_pci_alloc/drm_pci_free")
Cc: <stable@vger.kernel.org> # v4.5+
Cc: Tvrtko Ursulin <tursulin@ursulin.net>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_phys.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index e375afbf458e..d53129eb5603 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -18,6 +18,17 @@
 #include "i915_gem_tiling.h"
 #include "i915_scatterlist.h"
 
+/* Abuse scatterlist to store pointer instead of struct page. */
+static inline void __set_phys_vaddr(struct scatterlist *sg, void *vaddr)
+{
+	sg_assign_page(sg, (struct page *)vaddr);
+}
+
+static inline void *__get_phys_vaddr(struct scatterlist *sg)
+{
+	return (void *)sg_page(sg);
+}
+
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
 	struct address_space *mapping = obj->base.filp->f_mapping;
@@ -58,7 +69,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	sg->offset = 0;
 	sg->length = obj->base.size;
 
-	sg_assign_page(sg, (struct page *)vaddr);
+	__set_phys_vaddr(sg, vaddr);
 	sg_dma_address(sg) = dma;
 	sg_dma_len(sg) = obj->base.size;
 
@@ -99,7 +110,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
 			       struct sg_table *pages)
 {
 	dma_addr_t dma = sg_dma_address(pages->sgl);
-	void *vaddr = sg_page(pages->sgl);
+	void *vaddr = __get_phys_vaddr(pages->sgl);
 
 	__i915_gem_object_release_shmem(obj, pages, false);
 
@@ -139,7 +150,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
 int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
 				const struct drm_i915_gem_pwrite *args)
 {
-	void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
+	void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
 	char __user *user_data = u64_to_user_ptr(args->data_ptr);
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	int err;
@@ -170,7 +181,7 @@ int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
 int i915_gem_object_pread_phys(struct drm_i915_gem_object *obj,
 			       const struct drm_i915_gem_pread *args)
 {
-	void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
+	void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
 	char __user *user_data = u64_to_user_ptr(args->data_ptr);
 	int err;
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset
  2026-06-10  6:03 [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset Joonas Lahtinen
@ 2026-06-10  6:14 ` sashiko-bot
  2026-06-10  8:06 ` Tvrtko Ursulin
  2026-06-10 14:35 ` ✓ i915.CI.BAT: success for " Patchwork
  2 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-06-10  6:14 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: dri-devel

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

Pre-existing issues:
- [Critical] Integer overflow in `roundup_pow_of_two` on 32-bit systems causes a massive heap buffer overflow when allocating physically contiguous pages for large objects.
--

commit bdaf5470cc890b63dd50b4ef6b0bd2b13dcdaa7b
Author: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

drm/i915/gem: Fix phys BO pread/pwrite with offset

This commit fixes a scaling issue in phys BO pread/pwrite when using
non-zero offsets. It updates the code to correctly access the struct
page pointers via scatterlist abstractions instead of void pointers.

> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> index e375afbf458ee..d53129eb56030 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c

[ ... ]

> @@ -58,7 +69,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
>  	sg->offset = 0;
>  	sg->length = obj->base.size;
>  
> -	sg_assign_page(sg, (struct page *)vaddr);
> +	__set_phys_vaddr(sg, vaddr);

[Severity: Critical]
This is a pre-existing issue, but does the dma_alloc_coherent() allocation
earlier in this function overflow on 32-bit systems?

Looking at i915_gem_object_get_pages_phys(), we allocate memory using:

    vaddr = dma_alloc_coherent(obj->base.dev->dev,
                               roundup_pow_of_two(obj->base.size),
                               &dma, GFP_KERNEL);

If a user allocates a GEM object larger than 2GB (e.g., 0x80001000),
roundup_pow_of_two() calculates 1UL << fls_long(n - 1). On x86 32-bit,
shift amounts are masked to 5 bits, so 32 & 31 = 0, resulting in an
allocation size of 1 byte (which the allocator rounds up to PAGE_SIZE).

Later in the same function, a loop writes obj->base.size bytes into this
undersized buffer:

    for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
        struct page *page;

        page = shmem_read_mapping_page(mapping, i);
        if (IS_ERR(page))
            goto err_st;

        memcpy_from_page(dst, page, 0, PAGE_SIZE);
        drm_clflush_virt_range(dst, PAGE_SIZE);

        put_page(page);
        dst += PAGE_SIZE;
    }

Can this cause a massive buffer overflow and corrupt physical memory when
handling large objects?

>  	sg_dma_address(sg) = dma;
>  	sg_dma_len(sg) = obj->base.size;
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610060314.26111-1-joonas.lahtinen@linux.intel.com?part=1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset
  2026-06-10  6:03 [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset Joonas Lahtinen
  2026-06-10  6:14 ` sashiko-bot
@ 2026-06-10  8:06 ` Tvrtko Ursulin
  2026-06-10 14:35 ` ✓ i915.CI.BAT: success for " Patchwork
  2 siblings, 0 replies; 4+ messages in thread
From: Tvrtko Ursulin @ 2026-06-10  8:06 UTC (permalink / raw)
  To: Joonas Lahtinen,
	Intel graphics driver community testing & development
  Cc: Direct Rendering Infrastructure - Development,
	Matthew Wilcox (Oracle), stable, Simona Vetter, Jani Nikula,
	Rodrigo Vivi


On 10/06/2026 07:03, Joonas Lahtinen wrote:
> sg_page() returns struct page pointer not (void *) so the scaling
> of pread/pwrite is wrong for phys BO and wrong parts of BO would be
> accessed if non-zero offset is used.
> 
> Last impacted platform with overlay or cursor planes using phys
> mapping was Gen3/945G/Lakeport.
> 
> Reported-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Fixes: c6790dc22312 ("drm/i915: Wean off drm_pci_alloc/drm_pci_free")
> Cc: <stable@vger.kernel.org> # v4.5+
> Cc: Tvrtko Ursulin <tursulin@ursulin.net>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_phys.c | 19 +++++++++++++++----
>   1 file changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> index e375afbf458e..d53129eb5603 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> @@ -18,6 +18,17 @@
>   #include "i915_gem_tiling.h"
>   #include "i915_scatterlist.h"
>   
> +/* Abuse scatterlist to store pointer instead of struct page. */
> +static inline void __set_phys_vaddr(struct scatterlist *sg, void *vaddr)
> +{
> +	sg_assign_page(sg, (struct page *)vaddr);
> +}
> +
> +static inline void *__get_phys_vaddr(struct scatterlist *sg)
> +{
> +	return (void *)sg_page(sg);
> +}
> +
>   static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
>   {
>   	struct address_space *mapping = obj->base.filp->f_mapping;
> @@ -58,7 +69,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
>   	sg->offset = 0;
>   	sg->length = obj->base.size;
>   
> -	sg_assign_page(sg, (struct page *)vaddr);
> +	__set_phys_vaddr(sg, vaddr);
>   	sg_dma_address(sg) = dma;
>   	sg_dma_len(sg) = obj->base.size;
>   
> @@ -99,7 +110,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
>   			       struct sg_table *pages)
>   {
>   	dma_addr_t dma = sg_dma_address(pages->sgl);
> -	void *vaddr = sg_page(pages->sgl);
> +	void *vaddr = __get_phys_vaddr(pages->sgl);
>   
>   	__i915_gem_object_release_shmem(obj, pages, false);
>   
> @@ -139,7 +150,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
>   int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
>   				const struct drm_i915_gem_pwrite *args)
>   {
> -	void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
> +	void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
>   	char __user *user_data = u64_to_user_ptr(args->data_ptr);
>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>   	int err;
> @@ -170,7 +181,7 @@ int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
>   int i915_gem_object_pread_phys(struct drm_i915_gem_object *obj,
>   			       const struct drm_i915_gem_pread *args)
>   {
> -	void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
> +	void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
>   	char __user *user_data = u64_to_user_ptr(args->data_ptr);
>   	int err;
>   

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>

Regards,

Tvrtko


^ permalink raw reply	[flat|nested] 4+ messages in thread

* ✓ i915.CI.BAT: success for drm/i915/gem: Fix phys BO pread/pwrite with offset
  2026-06-10  6:03 [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset Joonas Lahtinen
  2026-06-10  6:14 ` sashiko-bot
  2026-06-10  8:06 ` Tvrtko Ursulin
@ 2026-06-10 14:35 ` Patchwork
  2 siblings, 0 replies; 4+ messages in thread
From: Patchwork @ 2026-06-10 14:35 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 1532 bytes --]

== Series Details ==

Series: drm/i915/gem: Fix phys BO pread/pwrite with offset
URL   : https://patchwork.freedesktop.org/series/168214/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_18654 -> Patchwork_168214v1
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_168214v1/index.html

Participating hosts (42 -> 39)
------------------------------

  Missing    (3): bat-dg2-13 fi-snb-2520m bat-adls-6 

Known issues
------------

  Here are the changes found in Patchwork_168214v1 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@core_auth@basic-auth:
    - fi-bsw-n3050:       [PASS][1] -> [DMESG-WARN][2] ([i915#16057])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18654/fi-bsw-n3050/igt@core_auth@basic-auth.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_168214v1/fi-bsw-n3050/igt@core_auth@basic-auth.html

  
  [i915#16057]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/16057


Build changes
-------------

  * Linux: CI_DRM_18654 -> Patchwork_168214v1

  CI-20190529: 20190529
  CI_DRM_18654: fc59f76558703febba8056be87d1c97d14f7485e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_8956: 8956
  Patchwork_168214v1: fc59f76558703febba8056be87d1c97d14f7485e @ git://anongit.freedesktop.org/gfx-ci/linux

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_168214v1/index.html

[-- Attachment #2: Type: text/html, Size: 2117 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-10 14:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10  6:03 [PATCH] drm/i915/gem: Fix phys BO pread/pwrite with offset Joonas Lahtinen
2026-06-10  6:14 ` sashiko-bot
2026-06-10  8:06 ` Tvrtko Ursulin
2026-06-10 14:35 ` ✓ i915.CI.BAT: success for " Patchwork

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.