* [PATCH] accel/ivpu: Validate scatter-gather size against buffer size
@ 2025-12-15 7:09 Karol Wachowski
2025-12-15 17:49 ` Lizhi Hou
0 siblings, 1 reply; 3+ messages in thread
From: Karol Wachowski @ 2025-12-15 7:09 UTC (permalink / raw)
To: dri-devel
Cc: oded.gabbay, jeff.hugo, maciej.falkowski, lizhi.hou,
andrzej.kacprowski, Karol Wachowski
Validate scatter-gather table size matches buffer object size before
mapping. Break mapping early if the table exceeds buffer size to
prevent overwriting existing mappings. Also validate the table is
not smaller than buffer size to avoid unmapped regions that trigger
MMU translation faults.
Log error and fail mapping operation on size mismatch to prevent
data corruption from mismatched host memory locations and NPU
addresses. Unmap any partially mapped buffer on failure.
Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
---
drivers/accel/ivpu/ivpu_gem.c | 2 +-
drivers/accel/ivpu/ivpu_mmu_context.c | 20 +++++++++++++++++---
drivers/accel/ivpu/ivpu_mmu_context.h | 5 +++--
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index ece68f570b7e..98b9ce26962b 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -95,7 +95,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
if (!bo->mmu_mapped) {
drm_WARN_ON(&vdev->drm, !bo->ctx);
- ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt,
+ ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt, ivpu_bo_size(bo),
ivpu_bo_is_snooped(bo), ivpu_bo_is_read_only(bo));
if (ret) {
ivpu_err(vdev, "Failed to map BO in MMU: %d\n", ret);
diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c
index 87ad593ef47d..c4014c83e727 100644
--- a/drivers/accel/ivpu/ivpu_mmu_context.c
+++ b/drivers/accel/ivpu/ivpu_mmu_context.c
@@ -429,11 +429,12 @@ static void ivpu_mmu_context_unmap_pages(struct ivpu_mmu_context *ctx, u64 vpu_a
}
int
-ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
- u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only)
+ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr,
+ struct sg_table *sgt, size_t bo_size, bool llc_coherent, bool read_only)
{
size_t start_vpu_addr = vpu_addr;
struct scatterlist *sg;
+ size_t sgt_size = 0;
int ret;
u64 prot;
u64 i;
@@ -462,12 +463,25 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
ivpu_dbg(vdev, MMU_MAP, "Map ctx: %u dma_addr: 0x%llx vpu_addr: 0x%llx size: %lu\n",
ctx->id, dma_addr, vpu_addr, size);
+ if (sgt_size + size > bo_size) {
+ ivpu_err(vdev, "Scatter-gather table size exceeds buffer object size\n");
+ ret = -EINVAL;
+ goto err_unmap_pages;
+ }
+
ret = ivpu_mmu_context_map_pages(vdev, ctx, vpu_addr, dma_addr, size, prot);
if (ret) {
ivpu_err(vdev, "Failed to map context pages\n");
goto err_unmap_pages;
}
vpu_addr += size;
+ sgt_size += size;
+ }
+
+ if (sgt_size < bo_size) {
+ ivpu_err(vdev, "Scatter-gather table size too small to cover buffer object size\n");
+ ret = -EINVAL;
+ goto err_unmap_pages;
}
if (!ctx->is_cd_valid) {
@@ -493,7 +507,7 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
return 0;
err_unmap_pages:
- ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, vpu_addr - start_vpu_addr);
+ ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, sgt_size);
mutex_unlock(&ctx->lock);
return ret;
}
diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h
index 663a11a9db11..cc02e7bab04e 100644
--- a/drivers/accel/ivpu/ivpu_mmu_context.h
+++ b/drivers/accel/ivpu/ivpu_mmu_context.h
@@ -41,8 +41,9 @@ int ivpu_mmu_context_insert_node(struct ivpu_mmu_context *ctx, const struct ivpu
u64 size, struct drm_mm_node *node);
void ivpu_mmu_context_remove_node(struct ivpu_mmu_context *ctx, struct drm_mm_node *node);
-int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
- u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only);
+int
+ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr,
+ struct sg_table *sgt, size_t bo_size, bool llc_coherent, bool read_only);
void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr, struct sg_table *sgt);
int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] accel/ivpu: Validate scatter-gather size against buffer size
2025-12-15 7:09 [PATCH] accel/ivpu: Validate scatter-gather size against buffer size Karol Wachowski
@ 2025-12-15 17:49 ` Lizhi Hou
2025-12-16 8:26 ` Karol Wachowski
0 siblings, 1 reply; 3+ messages in thread
From: Lizhi Hou @ 2025-12-15 17:49 UTC (permalink / raw)
To: Karol Wachowski, dri-devel
Cc: oded.gabbay, jeff.hugo, maciej.falkowski, andrzej.kacprowski
Reviewed-by: Lizhi Hou <lizhi.hou@amd.com>
On 12/14/25 23:09, Karol Wachowski wrote:
> Validate scatter-gather table size matches buffer object size before
> mapping. Break mapping early if the table exceeds buffer size to
> prevent overwriting existing mappings. Also validate the table is
> not smaller than buffer size to avoid unmapped regions that trigger
> MMU translation faults.
>
> Log error and fail mapping operation on size mismatch to prevent
> data corruption from mismatched host memory locations and NPU
> addresses. Unmap any partially mapped buffer on failure.
>
> Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
> ---
> drivers/accel/ivpu/ivpu_gem.c | 2 +-
> drivers/accel/ivpu/ivpu_mmu_context.c | 20 +++++++++++++++++---
> drivers/accel/ivpu/ivpu_mmu_context.h | 5 +++--
> 3 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
> index ece68f570b7e..98b9ce26962b 100644
> --- a/drivers/accel/ivpu/ivpu_gem.c
> +++ b/drivers/accel/ivpu/ivpu_gem.c
> @@ -95,7 +95,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
>
> if (!bo->mmu_mapped) {
> drm_WARN_ON(&vdev->drm, !bo->ctx);
> - ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt,
> + ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt, ivpu_bo_size(bo),
> ivpu_bo_is_snooped(bo), ivpu_bo_is_read_only(bo));
> if (ret) {
> ivpu_err(vdev, "Failed to map BO in MMU: %d\n", ret);
> diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c
> index 87ad593ef47d..c4014c83e727 100644
> --- a/drivers/accel/ivpu/ivpu_mmu_context.c
> +++ b/drivers/accel/ivpu/ivpu_mmu_context.c
> @@ -429,11 +429,12 @@ static void ivpu_mmu_context_unmap_pages(struct ivpu_mmu_context *ctx, u64 vpu_a
> }
>
> int
> -ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
> - u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only)
> +ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr,
> + struct sg_table *sgt, size_t bo_size, bool llc_coherent, bool read_only)
> {
> size_t start_vpu_addr = vpu_addr;
> struct scatterlist *sg;
> + size_t sgt_size = 0;
> int ret;
> u64 prot;
> u64 i;
> @@ -462,12 +463,25 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
> ivpu_dbg(vdev, MMU_MAP, "Map ctx: %u dma_addr: 0x%llx vpu_addr: 0x%llx size: %lu\n",
> ctx->id, dma_addr, vpu_addr, size);
>
> + if (sgt_size + size > bo_size) {
> + ivpu_err(vdev, "Scatter-gather table size exceeds buffer object size\n");
> + ret = -EINVAL;
> + goto err_unmap_pages;
> + }
> +
> ret = ivpu_mmu_context_map_pages(vdev, ctx, vpu_addr, dma_addr, size, prot);
> if (ret) {
> ivpu_err(vdev, "Failed to map context pages\n");
> goto err_unmap_pages;
> }
> vpu_addr += size;
> + sgt_size += size;
> + }
> +
> + if (sgt_size < bo_size) {
> + ivpu_err(vdev, "Scatter-gather table size too small to cover buffer object size\n");
> + ret = -EINVAL;
> + goto err_unmap_pages;
> }
>
> if (!ctx->is_cd_valid) {
> @@ -493,7 +507,7 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
> return 0;
>
> err_unmap_pages:
> - ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, vpu_addr - start_vpu_addr);
> + ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, sgt_size);
> mutex_unlock(&ctx->lock);
> return ret;
> }
> diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h
> index 663a11a9db11..cc02e7bab04e 100644
> --- a/drivers/accel/ivpu/ivpu_mmu_context.h
> +++ b/drivers/accel/ivpu/ivpu_mmu_context.h
> @@ -41,8 +41,9 @@ int ivpu_mmu_context_insert_node(struct ivpu_mmu_context *ctx, const struct ivpu
> u64 size, struct drm_mm_node *node);
> void ivpu_mmu_context_remove_node(struct ivpu_mmu_context *ctx, struct drm_mm_node *node);
>
> -int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
> - u64 vpu_addr, struct sg_table *sgt, bool llc_coherent, bool read_only);
> +int
> +ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr,
> + struct sg_table *sgt, size_t bo_size, bool llc_coherent, bool read_only);
> void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
> u64 vpu_addr, struct sg_table *sgt);
> int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] accel/ivpu: Validate scatter-gather size against buffer size
2025-12-15 17:49 ` Lizhi Hou
@ 2025-12-16 8:26 ` Karol Wachowski
0 siblings, 0 replies; 3+ messages in thread
From: Karol Wachowski @ 2025-12-16 8:26 UTC (permalink / raw)
To: Lizhi Hou, dri-devel
Cc: oded.gabbay, jeff.hugo, maciej.falkowski, andrzej.kacprowski
On 12/15/2025 6:49 PM, Lizhi Hou wrote:
> Reviewed-by: Lizhi Hou <lizhi.hou@amd.com>
Thank you. Applied to drm-misc-next.
Karol>
> On 12/14/25 23:09, Karol Wachowski wrote:
>> Validate scatter-gather table size matches buffer object size before
>> mapping. Break mapping early if the table exceeds buffer size to
>> prevent overwriting existing mappings. Also validate the table is
>> not smaller than buffer size to avoid unmapped regions that trigger
>> MMU translation faults.
>>
>> Log error and fail mapping operation on size mismatch to prevent
>> data corruption from mismatched host memory locations and NPU
>> addresses. Unmap any partially mapped buffer on failure.
>>
>> Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
>> ---
>> drivers/accel/ivpu/ivpu_gem.c | 2 +-
>> drivers/accel/ivpu/ivpu_mmu_context.c | 20 +++++++++++++++++---
>> drivers/accel/ivpu/ivpu_mmu_context.h | 5 +++--
>> 3 files changed, 21 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/
>> ivpu_gem.c
>> index ece68f570b7e..98b9ce26962b 100644
>> --- a/drivers/accel/ivpu/ivpu_gem.c
>> +++ b/drivers/accel/ivpu/ivpu_gem.c
>> @@ -95,7 +95,7 @@ int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
>> if (!bo->mmu_mapped) {
>> drm_WARN_ON(&vdev->drm, !bo->ctx);
>> - ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr, sgt,
>> + ret = ivpu_mmu_context_map_sgt(vdev, bo->ctx, bo->vpu_addr,
>> sgt, ivpu_bo_size(bo),
>> ivpu_bo_is_snooped(bo),
>> ivpu_bo_is_read_only(bo));
>> if (ret) {
>> ivpu_err(vdev, "Failed to map BO in MMU: %d\n", ret);
>> diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/
>> ivpu/ivpu_mmu_context.c
>> index 87ad593ef47d..c4014c83e727 100644
>> --- a/drivers/accel/ivpu/ivpu_mmu_context.c
>> +++ b/drivers/accel/ivpu/ivpu_mmu_context.c
>> @@ -429,11 +429,12 @@ static void ivpu_mmu_context_unmap_pages(struct
>> ivpu_mmu_context *ctx, u64 vpu_a
>> }
>> int
>> -ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
>> - u64 vpu_addr, struct sg_table *sgt, bool llc_coherent,
>> bool read_only)
>> +ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx, u64 vpu_addr,
>> + struct sg_table *sgt, size_t bo_size, bool llc_coherent,
>> bool read_only)
>> {
>> size_t start_vpu_addr = vpu_addr;
>> struct scatterlist *sg;
>> + size_t sgt_size = 0;
>> int ret;
>> u64 prot;
>> u64 i;
>> @@ -462,12 +463,25 @@ ivpu_mmu_context_map_sgt(struct ivpu_device
>> *vdev, struct ivpu_mmu_context *ctx,
>> ivpu_dbg(vdev, MMU_MAP, "Map ctx: %u dma_addr: 0x%llx
>> vpu_addr: 0x%llx size: %lu\n",
>> ctx->id, dma_addr, vpu_addr, size);
>> + if (sgt_size + size > bo_size) {
>> + ivpu_err(vdev, "Scatter-gather table size exceeds buffer
>> object size\n");
>> + ret = -EINVAL;
>> + goto err_unmap_pages;
>> + }
>> +
>> ret = ivpu_mmu_context_map_pages(vdev, ctx, vpu_addr,
>> dma_addr, size, prot);
>> if (ret) {
>> ivpu_err(vdev, "Failed to map context pages\n");
>> goto err_unmap_pages;
>> }
>> vpu_addr += size;
>> + sgt_size += size;
>> + }
>> +
>> + if (sgt_size < bo_size) {
>> + ivpu_err(vdev, "Scatter-gather table size too small to cover
>> buffer object size\n");
>> + ret = -EINVAL;
>> + goto err_unmap_pages;
>> }
>> if (!ctx->is_cd_valid) {
>> @@ -493,7 +507,7 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev,
>> struct ivpu_mmu_context *ctx,
>> return 0;
>> err_unmap_pages:
>> - ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, vpu_addr -
>> start_vpu_addr);
>> + ivpu_mmu_context_unmap_pages(ctx, start_vpu_addr, sgt_size);
>> mutex_unlock(&ctx->lock);
>> return ret;
>> }
>> diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/
>> ivpu/ivpu_mmu_context.h
>> index 663a11a9db11..cc02e7bab04e 100644
>> --- a/drivers/accel/ivpu/ivpu_mmu_context.h
>> +++ b/drivers/accel/ivpu/ivpu_mmu_context.h
>> @@ -41,8 +41,9 @@ int ivpu_mmu_context_insert_node(struct
>> ivpu_mmu_context *ctx, const struct ivpu
>> u64 size, struct drm_mm_node *node);
>> void ivpu_mmu_context_remove_node(struct ivpu_mmu_context *ctx,
>> struct drm_mm_node *node);
>> -int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
>> - u64 vpu_addr, struct sg_table *sgt, bool
>> llc_coherent, bool read_only);
>> +int
>> +ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx, u64 vpu_addr,
>> + struct sg_table *sgt, size_t bo_size, bool llc_coherent,
>> bool read_only);
>> void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
>> u64 vpu_addr, struct sg_table *sgt);
>> int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-12-16 8:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-15 7:09 [PATCH] accel/ivpu: Validate scatter-gather size against buffer size Karol Wachowski
2025-12-15 17:49 ` Lizhi Hou
2025-12-16 8:26 ` Karol Wachowski
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.