[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221007013708.1946061-1-zyytlz.wz@163.com>
Date: Fri, 7 Oct 2022 09:37:08 +0800
From: Zheng Wang <zyytlz.wz@....com>
To: gregkh@...uxfoundation.org
Cc: 1002992920@...com, airlied@...ux.ie, alex000young@...il.com,
dri-devel@...ts.freedesktop.org, hackerzheng666@...il.com,
intel-gfx@...ts.freedesktop.org, linux-kernel@...r.kernel.org,
security@...nel.org, zyytlz.wz@....com
Subject: [PATCH v3] drm/i915/gvt: fix double free bug in split_2MB_gtt_entry
If intel_gvt_dma_map_guest_page failed, it will call
ppgtt_invalidate_spt, which will finally free the spt.
But the caller does not notice that, it will free spt again in error path.
Fix this by spliting invalidate and free in ppgtt_invalidate_spt.
Only free spt when in good case.
Reported-by: Zheng Wang <hackerzheng666@...il.com>
Signed-off-by: Zheng Wang <zyytlz.wz@....com>
---
v3:
- correct spelling mistake and remove unused variable suggested by Greg
v2: https://lore.kernel.org/all/20221006165845.1735393-1-zyytlz.wz@163.com/
v1: https://lore.kernel.org/all/20220928033340.1063949-1-zyytlz.wz@163.com/
---
drivers/gpu/drm/i915/gvt/gtt.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index ce0eb03709c3..865d33762e45 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -959,6 +959,7 @@ static inline int ppgtt_put_spt(struct intel_vgpu_ppgtt_spt *spt)
return atomic_dec_return(&spt->refcount);
}
+static int ppgtt_invalidate_and_free_spt(struct intel_vgpu_ppgtt_spt *spt);
static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt);
static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
@@ -995,7 +996,7 @@ static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
ops->get_pfn(e));
return -ENXIO;
}
- return ppgtt_invalidate_spt(s);
+ return ppgtt_invalidate_and_free_spt(s);
}
static inline void ppgtt_invalidate_pte(struct intel_vgpu_ppgtt_spt *spt,
@@ -1016,18 +1017,30 @@ static inline void ppgtt_invalidate_pte(struct intel_vgpu_ppgtt_spt *spt,
intel_gvt_dma_unmap_guest_page(vgpu, pfn << PAGE_SHIFT);
}
-static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
+static int ppgtt_invalidate_and_free_spt(struct intel_vgpu_ppgtt_spt *spt)
{
- struct intel_vgpu *vgpu = spt->vgpu;
- struct intel_gvt_gtt_entry e;
- unsigned long index;
int ret;
trace_spt_change(spt->vgpu->id, "die", spt,
- spt->guest_page.gfn, spt->shadow_page.type);
-
+ spt->guest_page.gfn, spt->shadow_page.type);
if (ppgtt_put_spt(spt) > 0)
return 0;
+ ret = ppgtt_invalidate_spt(spt);
+ if (!ret) {
+ trace_spt_change(spt->vgpu->id, "release", spt,
+ spt->guest_page.gfn, spt->shadow_page.type);
+ ppgtt_free_spt(spt);
+ }
+
+ return ret;
+}
+
+static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
+{
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_gvt_gtt_entry e;
+ unsigned long index;
+ int ret;
for_each_present_shadow_entry(spt, &e, index) {
switch (e.type) {
@@ -1059,9 +1072,6 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
}
}
- trace_spt_change(spt->vgpu->id, "release", spt,
- spt->guest_page.gfn, spt->shadow_page.type);
- ppgtt_free_spt(spt);
return 0;
fail:
gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n",
@@ -1393,7 +1403,7 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_ppgtt_spt *spt,
ret = -ENXIO;
goto fail;
}
- ret = ppgtt_invalidate_spt(s);
+ ret = ppgtt_invalidate_and_free_spt(s);
if (ret)
goto fail;
} else {
--
2.25.1
Powered by blists - more mailing lists