From: Ray Wu Date: Tue, 7 Apr 2026 08:24:39 +0000 (+0800) Subject: drm/amd/display: fix NULL ptr deref in ISM delayed work X-Git-Tag: v7.1-rc1~24^2~3^2~22 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=17edfa32f1496df914b355cf7c0711a481765446;p=thirdparty%2Fkernel%2Flinux.git drm/amd/display: fix NULL ptr deref in ISM delayed work dc_destroy() sets dm->dc to NULL before amdgpu_dm_ism_fini() is called, leaving a window where in-flight ISM delayed work dereferences the stale pointer. Call amdgpu_dm_ism_fini() in amdgpu_dm_fini() before dc_destroy(). Fixes: 754003486c3c ("drm/amd/display: Add Idle state manager(ISM)") Reviewed-by: Leo Li Signed-off-by: Ray Wu Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f69a7e88546a..f4be2724471d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2239,6 +2239,8 @@ static int amdgpu_dm_early_fini(struct amdgpu_ip_block *ip_block) static void amdgpu_dm_fini(struct amdgpu_device *adev) { int i; + struct drm_crtc *crtc; + struct amdgpu_crtc *acrtc; if (adev->dm.vblank_control_workqueue) { destroy_workqueue(adev->dm.vblank_control_workqueue); @@ -2255,6 +2257,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.idle_workqueue = NULL; } + /* Finalize ISM for each CRTC before dc_destroy() sets dm->dc to NULL */ + drm_for_each_crtc(crtc, adev_to_drm(adev)) { + acrtc = to_amdgpu_crtc(crtc); + amdgpu_dm_ism_fini(&acrtc->ism); + + } + amdgpu_dm_destroy_drm_device(&adev->dm); #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 5d2715f78314..d69f5a75b685 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -457,9 +457,12 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + /* + * amdgpu_dm_ism_fini() is intentionally called in amdgpu_dm_fini(). + * It must be called before dc_destroy() in amdgpu_dm_fini() + * to avoid ISM accessing an invalid dc handle once dc is released. + */ - amdgpu_dm_ism_fini(&acrtc->ism); drm_crtc_cleanup(crtc); kfree(crtc); }