Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <sunpeng.li@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Ray Wu and committed by
Alex Deucher
17edfa32 7949927a

+14 -2
+9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 2239 2239 static void amdgpu_dm_fini(struct amdgpu_device *adev) 2240 2240 { 2241 2241 int i; 2242 + struct drm_crtc *crtc; 2243 + struct amdgpu_crtc *acrtc; 2242 2244 2243 2245 if (adev->dm.vblank_control_workqueue) { 2244 2246 destroy_workqueue(adev->dm.vblank_control_workqueue); ··· 2255 2253 2256 2254 kfree(adev->dm.idle_workqueue); 2257 2255 adev->dm.idle_workqueue = NULL; 2256 + } 2257 + 2258 + /* Finalize ISM for each CRTC before dc_destroy() sets dm->dc to NULL */ 2259 + drm_for_each_crtc(crtc, adev_to_drm(adev)) { 2260 + acrtc = to_amdgpu_crtc(crtc); 2261 + amdgpu_dm_ism_fini(&acrtc->ism); 2262 + 2258 2263 } 2259 2264 2260 2265 amdgpu_dm_destroy_drm_device(&adev->dm);
+5 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
··· 457 457 458 458 static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) 459 459 { 460 - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); 460 + /* 461 + * amdgpu_dm_ism_fini() is intentionally called in amdgpu_dm_fini(). 462 + * It must be called before dc_destroy() in amdgpu_dm_fini() 463 + * to avoid ISM accessing an invalid dc handle once dc is released. 464 + */ 461 465 462 - amdgpu_dm_ism_fini(&acrtc->ism); 463 466 drm_crtc_cleanup(crtc); 464 467 kfree(crtc); 465 468 }