diff options
| author | Zhenhao Wan <whi4ed0g@gmail.com> | 2026-08-11 16:46:28 +0800 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-09-01 10:18:00 +0200 |
| commit | 412a6ceb56d501ef2f8202e26ab4b5d4dfbca566 (patch) | |
| tree | 2abb6cd3bd8e20ef7a0bc47c74f7a4c81f8ba1fa /drivers/gpu | |
| parent | 67f8bc848ee31831336bd478e57d2f993551902e (diff) | |
| download | linux-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/gpu')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_uvmm.c | 3 |
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; } |
