summaryrefslogtreecommitdiff
path: root/drivers/accel
diff options
context:
space:
mode:
authorDhabaleshwar Das <dhabal123@gmail.com>2026-05-21 00:00:00 +0530
committerTomeu Vizoso <tomeu@tomeuvizoso.net>2026-05-21 19:01:23 +0200
commitf706e6a4ce75585af979aec3dcbdce68bc76306b (patch)
treef0e4d0c987709ad7e753dc1746a5e8007b27f0c4 /drivers/accel
parent9af1b6e175c82daf4b423da339a722d8e67a735a (diff)
accel/rocket: fix UAF via dangling GEM handle in create_bo
rocket_ioctl_create_bo() inserts a GEM handle into the file's IDR via drm_gem_handle_create() early on, then performs several operations that can fail (sgt allocation, drm_mm insert, iommu_map). If any fail after the handle is live, the error path calls drm_gem_shmem_object_free() which kfree's the object without removing the handle from the IDR. This leaves a dangling handle pointing to freed slab memory. Any subsequent ioctl using that handle (PREP_BO, FINI_BO, SUBMIT) calls drm_gem_object_lookup() and dereferences freed memory (UAF). Fix by moving drm_gem_handle_create() to after all fallible operations succeed, matching the pattern used by panfrost, lima, and etnaviv. Also fix drm_mm_insert_node_generic() whose return value was silently overwritten by iommu_map_sgtable() on the next line. Add the missing error check. [tomeu: Move handle creation to the very end] Fixes: 658ebeac3351 ("accel/rocket: Add IOCTL for BO creation") Reported-by: Dhabaleshwar Das <dhabal123@gmail.com> Signed-off-by: Dhabaleshwar Das <dhabal123@gmail.com> Reviewed-by: Tomeu Vizoso <tomeu@tomeuvizoso.net> Link: https://patch.msgid.link/20260521165720.2113571-1-tomeu@tomeuvizoso.net Signed-off-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
Diffstat (limited to 'drivers/accel')
-rw-r--r--drivers/accel/rocket/rocket_gem.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/accel/rocket/rocket_gem.c b/drivers/accel/rocket/rocket_gem.c
index c8084719208a..a5fffa51ff35 100644
--- a/drivers/accel/rocket/rocket_gem.c
+++ b/drivers/accel/rocket/rocket_gem.c
@@ -79,11 +79,6 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size = args->size;
rkt_obj->offset = 0;
- ret = drm_gem_handle_create(file, gem_obj, &args->handle);
- drm_gem_object_put(gem_obj);
- if (ret)
- goto err;
-
sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
@@ -95,6 +90,8 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size, PAGE_SIZE,
0, 0);
mutex_unlock(&rocket_priv->mm_lock);
+ if (ret)
+ goto err;
ret = iommu_map_sgtable(rocket_priv->domain->domain,
rkt_obj->mm.start,
@@ -112,8 +109,18 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
args->dma_address = rkt_obj->mm.start;
+ ret = drm_gem_handle_create(file, gem_obj, &args->handle);
+ if (ret)
+ goto err_unmap;
+
+ drm_gem_object_put(gem_obj);
+
return 0;
+err_unmap:
+ iommu_unmap(rocket_priv->domain->domain,
+ rkt_obj->mm.start, rkt_obj->size);
+
err_remove_node:
mutex_lock(&rocket_priv->mm_lock);
drm_mm_remove_node(&rkt_obj->mm);