]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/i915/gvt: fix double free bug in split_2MB_gtt_entry
authorZheng Wang <zyytlz.wz@163.com>
Thu, 29 Dec 2022 16:56:41 +0000 (00:56 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 Feb 2023 10:53:26 +0000 (11:53 +0100)
commit 587ea5e52f0bdaf767e32acd16eebb6837bc84b0 upstream.

If intel_gvt_dma_map_guest_page failed, it will call
ppgtt_invalidate_spt, which will finally free the spt.
But the caller function ppgtt_populate_spt_by_guest_entry
does not notice that, it will free spt again in its error
path.

Fix this by canceling the mapping of DMA address and freeing sub_spt.
Besides, leave the handle of spt destroy to caller function instead
of callee function when error occurs.

Fixes: a97ac69b4b38 ("drm/i915/gvt: Add 2M huge gtt support")
Signed-off-by: Zheng Wang <zyytlz.wz@163.com>
Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20221229165641.1192455-1-zyytlz.wz@163.com
Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/i915/gvt/gtt.c

index 7dc7bb850d0a67df92e47f74ef31232e329a68d3..a7913410003d85efa7cf4bc37051a6a43b25cf6a 100644 (file)
@@ -1186,10 +1186,8 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu,
        for_each_shadow_entry(sub_spt, &sub_se, sub_index) {
                ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
                                start_gfn + sub_index, PAGE_SIZE, &dma_addr);
-               if (ret) {
-                       ppgtt_invalidate_spt(spt);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
                sub_se.val64 = se->val64;
 
                /* Copy the PAT field from PDE. */
@@ -1208,6 +1206,17 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu,
        ops->set_pfn(se, sub_spt->shadow_page.mfn);
        ppgtt_set_shadow_entry(spt, se, index);
        return 0;
+err:
+       /* Cancel the existing addess mappings of DMA addr. */
+       for_each_present_shadow_entry(sub_spt, &sub_se, sub_index) {
+               gvt_vdbg_mm("invalidate 4K entry\n");
+               ppgtt_invalidate_pte(sub_spt, &sub_se);
+       }
+       /* Release the new allocated spt. */
+       trace_spt_change(sub_spt->vgpu->id, "release", sub_spt,
+               sub_spt->guest_page.gfn, sub_spt->shadow_page.type);
+       ppgtt_free_spt(sub_spt);
+       return ret;
 }
 
 static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,