summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mediatek
diff options
context:
space:
mode:
authorHsin-Yi Wang <hsinyi@chromium.org>2024-02-24 00:23:29 +0300
committerSasha Levin <sashal@kernel.org>2024-03-27 01:19:54 +0300
commita3dd12b64ae8373a41a216a0b621df224210860a (patch)
tree0cbd52d8d2d67b888eca7f0bcacc2153cc1b45a8 /drivers/gpu/drm/mediatek
parent37e0f758e0573fefab300cfd602a4a0a1709678c (diff)
downloadlinux-a3dd12b64ae8373a41a216a0b621df224210860a.tar.xz
drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
[ Upstream commit c958e86e9cc1b48cac004a6e245154dfba8e163b ] 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: 119f5173628a ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/mediatek')
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 80e34b39a6b1..29e021ec6901 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -93,11 +93,13 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
struct drm_crtc *crtc = &mtk_crtc->base;
unsigned long flags;
- spin_lock_irqsave(&crtc->dev->event_lock, flags);
- drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
- drm_crtc_vblank_put(crtc);
- mtk_crtc->event = NULL;
- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ if (mtk_crtc->event) {
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
+ drm_crtc_vblank_put(crtc);
+ mtk_crtc->event = NULL;
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ }
}
static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)