summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorZhenhao Wan <whi4ed0g@gmail.com>2026-08-11 16:46:28 +0800
committerDanilo Krummrich <dakr@kernel.org>2026-09-01 10:18:00 +0200
commit412a6ceb56d501ef2f8202e26ab4b5d4dfbca566 (patch)
tree2abb6cd3bd8e20ef7a0bc47c74f7a4c81f8ba1fa /drivers
parent67f8bc848ee31831336bd478e57d2f993551902e (diff)
downloadlinux-412a6ceb56d501ef2f8202e26ab4b5d4dfbca566.tar.gz
linux-412a6ceb56d501ef2f8202e26ab4b5d4dfbca566.zip
drm/nouveau/uvmm: fix NULL deref unwinding an OP_MAP_SPARSE op
Each bind_job_op is zeroed by kzalloc_obj() in bind_job_op_from_uop(), and the OP_MAP_SPARSE case in nouveau_uvmm_bind_job_submit() only creates a region, so op->ops stays NULL for a successfully processed sparse map. If a later op in the same job fails, the reverse unwind loop revisits that op and calls drm_gpuva_ops_free(&uvmm->base, op->ops) unconditionally. drm_gpuva_ops_free() dereferences its argument right away (list_for_each_entry_safe on &ops->list), so a NULL op->ops oopses. The path is reachable by any render-node fd holder, since NOUVEAU_VM_BIND is DRM_RENDER_ALLOW. Guard the free with IS_ERR_OR_NULL(), as nouveau_uvmm_bind_job_cleanup() already does for the identical free. Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI") Reported-by: Yuhao Jiang <danisjiang@gmail.com> Assisted-by: Claude:claude-opus-5 Cc: stable@vger.kernel.org Signed-off-by: Zhenhao Wan <whi4ed0g@gmail.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patch.msgid.link/20260811-nouveau-uvmm-vmbind-fixes-v2-1-aaee4b395d04@gmail.com Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_uvmm.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index f5e4756b4de4..19e758a20c24 100644
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1489,7 +1489,8 @@ unwind:
break;
}
- drm_gpuva_ops_free(&uvmm->base, op->ops);
+ if (!IS_ERR_OR_NULL(op->ops))
+ drm_gpuva_ops_free(&uvmm->base, op->ops);
op->ops = NULL;
op->reg = NULL;
}