History

drm/i915: Fix vm use-after-free in vma destruction

In vma destruction, the following race may occur: Thread 1: Thread 2: i915_vma_destroy(); ... list_del_init(vma->vm_link); ... mutex_unlock(vma->vm->mutex); __i915_vm_release(); release_references(); And in release_reference() we dereference vma->vm to get to the vm gt pointer, leading to a use-after free. However, __i915_vm_release() grabs the vm->mutex so the vm won't be destroyed before vma->vm->mutex is released, so extract the gt pointer under the vm->mutex to avoid the vma->vm dereference in release_references(). v2: Fix a typo in the commit message (Andi Shyti) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5944 Fixes: e1a7ab4fca0c ("drm/i915: Remove the vm open count")

Thomas Hellström committed 4 years ago

Commit 48da0f61 parent 1391b9c1 file · +8 −4Browse files

Unified · Split

drivers/gpu/drm/i915/i915_vma.c+8−4
@@ -1637,10 +1637,10 @@ static void force_unbind(struct i915_vma *vma) · 1636 unmodified lines
16371637 GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
16381638 }
16391639
1640−static void release_references(struct i915_vma *vma, bool vm_ddestroy)
1640+static void release_references(struct i915_vma *vma, struct intel_gt *gt,
1641+ bool vm_ddestroy)
16411642 {
16421643 struct drm_i915_gem_object *obj = vma->obj;
1643− struct intel_gt *gt = vma->vm->gt;
16441644
16451645 GEM_BUG_ON(i915_vma_is_active(vma));
16461646
@@ -1695,11 +1695,12 @@ void i915_vma_destroy_locked(struct i915_vma *vma) · 48 unmodified lines
16951695
16961696 force_unbind(vma);
16971697 list_del_init(&vma->vm_link);
1698− release_references(vma, false);
1698+ release_references(vma, vma->vm->gt, false);
16991699 }
17001700
17011701 void i915_vma_destroy(struct i915_vma *vma)
17021702 {
1703+ struct intel_gt *gt;
17031704 bool vm_ddestroy;
17041705
17051706 mutex_lock(&vma->vm->mutex);
@@ -1707,8 +1708,11 @@ void i915_vma_destroy(struct i915_vma *vma) · 1 unmodified line
17071708 list_del_init(&vma->vm_link);
17081709 vm_ddestroy = vma->vm_ddestroy;
17091710 vma->vm_ddestroy = false;
1711+
1712+ /* vma->vm may be freed when releasing vma->vm->mutex. */
1713+ gt = vma->vm->gt;
17101714 mutex_unlock(&vma->vm->mutex);
1711− release_references(vma, vm_ddestroy);
1715+ release_references(vma, gt, vm_ddestroy);
17121716 }
17131717
17141718 void i915_vma_parked(struct intel_gt *gt)