summaryrefslogtreecommitdiff
path: root/drivers/accel
diff options
context:
space:
mode:
authorZack McKevitt <zachary.mckevitt@oss.qualcomm.com>2026-04-30 12:39:01 -0700
committerJeff Hugo <jeff.hugo@oss.qualcomm.com>2026-05-12 10:58:18 -0600
commitaa16b2bc0f02709919e2435f531406531e5bcc69 (patch)
treefb46615e7e592cdcce6726f46c5e6a78c0c0c01c /drivers/accel
parent53597deca0e38c30e6cd4ba2114fa42d2bcd85bb (diff)
downloadlinux-next-aa16b2bc0f02709919e2435f531406531e5bcc69.tar.gz
linux-next-aa16b2bc0f02709919e2435f531406531e5bcc69.zip
accel/qaic: Add overflow check to remap_pfn_range during mmap
The call to remap_pfn_range in qaic_gem_object_mmap is susceptible to (re)mapping beyond the VMA if the BO is too large. This can cause use after free issues when munmap() unmaps only the VMA region and not the additional mappings. To prevent this, check the remaining size of the VMA before remapping and truncate the remapped length if sg->length is too large. Reported-by: Lukas Maar <lukas.maar@tugraz.at> Fixes: ff13be830333 ("accel/qaic: Add datapath") Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com> Signed-off-by: Zack McKevitt <zachary.mckevitt@oss.qualcomm.com> Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com> [jhugo: fix braces from checkpatch --strict] Signed-off-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com> Link: https://patch.msgid.link/20260430193858.1178641-1-zachary.mckevitt@oss.qualcomm.com
Diffstat (limited to 'drivers/accel')
-rw-r--r--drivers/accel/qaic/qaic_data.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
index 95300c2f7d8a..1e4c579d2725 100644
--- a/drivers/accel/qaic/qaic_data.c
+++ b/drivers/accel/qaic/qaic_data.c
@@ -606,8 +606,11 @@ static const struct vm_operations_struct drm_vm_ops = {
static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
struct qaic_bo *bo = to_qaic_bo(obj);
+ unsigned long remap_start;
unsigned long offset = 0;
+ unsigned long remap_end;
struct scatterlist *sg;
+ unsigned long length;
int ret = 0;
if (drm_gem_is_imported(obj))
@@ -615,11 +618,27 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc
for (sg = bo->sgt->sgl; sg; sg = sg_next(sg)) {
if (sg_page(sg)) {
+ /* if sg is too large for the VMA, so truncate it to fit */
+ if (check_add_overflow(vma->vm_start, offset, &remap_start))
+ return -EINVAL;
+ if (check_add_overflow(remap_start, sg->length, &remap_end))
+ return -EINVAL;
+
+ if (remap_end > vma->vm_end) {
+ if (check_sub_overflow(vma->vm_end, remap_start, &length))
+ return -EINVAL;
+ } else {
+ length = sg->length;
+ }
+
+ if (length == 0)
+ goto out;
+
ret = remap_pfn_range(vma, vma->vm_start + offset, page_to_pfn(sg_page(sg)),
- sg->length, vma->vm_page_prot);
+ length, vma->vm_page_prot);
if (ret)
goto out;
- offset += sg->length;
+ offset += length;
}
}