Blob Blame History Raw
From 4979524f5a2a8210e87fde2f642b0dc060860821 Mon Sep 17 00:00:00 2001
From: Shang XiaoJing <shangxiaojing@huawei.com>
Date: Tue, 1 Nov 2022 15:07:16 +0800
Subject: [PATCH] drm: Fix potential null-ptr-deref in drm_vblank_destroy_worker()
Git-commit: 4979524f5a2a8210e87fde2f642b0dc060860821
Patch-mainline: v6.1-rc6
References: git-fixes

drm_vblank_init() call drmm_add_action_or_reset() with
drm_vblank_init_release() as action. If __drmm_add_action() failed, will
directly call drm_vblank_init_release() with the vblank whose worker is
NULL. As the resule, a null-ptr-deref will happen in
kthread_destroy_worker(). Add the NULL check before calling
drm_vblank_destroy_worker().

Bug: null-ptr-deref
Kasan: null-ptr-deref in range [0x0000000000000068-0x000000000000006f]
Cpu: 5 PID: 961 Comm: modprobe Not tainted 6.0.0-11331-gd465bff130bf-dirty
Rip: 0010:kthread_destroy_worker+0x25/0xb0  Call Trace:    <TASK>    drm_vblank_init_release+0x124/0x220 [drm]    ? drm_crtc_vblank_restore+0x8b0/0x8b0 [drm]    __drmm_add_action_or_reset+0x41/0x50 [drm]    drm_vblank_init+0x282/0x310 [drm]    vkms_init+0x35f/0x1000 [vkms]    ? 0xffffffffc4508000    ? lock_is_held_type+0xd7/0x130    ? __kmem_cache_alloc_node+0x1c2/0x2b0    ? lock_is_held_type+0xd7/0x130    ? 0xffffffffc4508000    do_one_initcall+0xd0/0x4f0    ...    do_syscall_64+0x35/0x80    entry_SYSCALL_64_after_hwframe+0x46/0xb0

Fixes: 5e6c2b4f9161 ("drm/vblank: Add vblank works")
Signed-off-by: Shang XiaoJing <shangxiaojing@huawei.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221101070716.9189-3-shangxiaojing@huawei.com
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/drm_internal.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 7bb98e6a446d..5ea5e260118c 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -104,7 +104,8 @@ static inline void drm_vblank_flush_worker(struct drm_vblank_crtc *vblank)
 
 static inline void drm_vblank_destroy_worker(struct drm_vblank_crtc *vblank)
 {
-	kthread_destroy_worker(vblank->worker);
+	if (vblank->worker)
+		kthread_destroy_worker(vblank->worker);
 }
 
 int drm_vblank_worker_init(struct drm_vblank_crtc *vblank);
-- 
2.35.3