Skip to content

Commit c958e86

Browse files
hsinyi527Chun-Kuang Hu
authored andcommitted
drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
It's possible that mtk_crtc->event is NULL in mtk_drm_crtc_finish_page_flip(). pending_needs_vblank value is set by mtk_crtc->event, but in mtk_drm_crtc_atomic_flush(), it's is not guarded by the same lock in mtk_drm_finish_page_flip(), thus a race condition happens. Consider the following case: CPU1 CPU2 step 1: mtk_drm_crtc_atomic_begin() mtk_crtc->event is not null, step 1: mtk_drm_crtc_atomic_flush: mtk_drm_crtc_update_config( !!mtk_crtc->event) step 2: mtk_crtc_ddp_irq -> mtk_drm_finish_page_flip: lock mtk_crtc->event set to null, pending_needs_vblank set to false unlock pending_needs_vblank set to true, step 2: mtk_crtc_ddp_irq -> mtk_drm_finish_page_flip called again, pending_needs_vblank is still true //null pointer Instead of guarding the entire mtk_drm_crtc_atomic_flush(), it's more efficient to just check if mtk_crtc->event is null before use. Fixes: 119f517 ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.") Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org> Reviewed-by: CK Hu <ck.hu@mediatek.com> Link: https://patchwork.kernel.org/project/dri-devel/patch/20240223212404.3709690-1-hsinyi@chromium.org/ Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
1 parent 5306b3f commit c958e86

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/gpu/drm/mediatek/mtk_drm_crtc.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
9595
struct drm_crtc *crtc = &mtk_crtc->base;
9696
unsigned long flags;
9797

98-
spin_lock_irqsave(&crtc->dev->event_lock, flags);
99-
drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
100-
drm_crtc_vblank_put(crtc);
101-
mtk_crtc->event = NULL;
102-
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
98+
if (mtk_crtc->event) {
99+
spin_lock_irqsave(&crtc->dev->event_lock, flags);
100+
drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
101+
drm_crtc_vblank_put(crtc);
102+
mtk_crtc->event = NULL;
103+
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
104+
}
103105
}
104106

105107
static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)

0 commit comments

Comments
 (0)