From 5c021a2f69d2e74457f4953be44d55fa07262240 Mon Sep 17 00:00:00 2001 From: dumbbell Date: Wed, 4 Mar 2015 20:43:46 +0000 Subject: drm: Import Linux commit b7ea85a4fed37835eec78a7be3039c8dc22b8178 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Author: Huacai Chen Date: Tue May 21 06:23:43 2013 +0000 drm: fix a use-after-free when GPU acceleration disabled When GPU acceleration is disabled, drm_vblank_cleanup() will free the vblank-related data, such as vblank_refcount, vblank_inmodeset, etc. But we found that drm_vblank_post_modeset() may be called after the cleanup, which use vblank_refcount and vblank_inmodeset. And this will cause a kernel panic. Fix this by return immediately if dev->num_crtcs is zero. This is the same thing that drm_vblank_pre_modeset() does. Call trace of a drm_vblank_post_modeset() after drm_vblank_cleanup(): [ 62.628906] [] drm_vblank_post_modeset+0x34/0xb4 [ 62.628906] [] atombios_crtc_dpms+0xb4/0x174 [ 62.628906] [] atombios_crtc_commit+0x18/0x38 [ 62.628906] [] drm_crtc_helper_set_mode+0x304/0x3cc [ 62.628906] [] drm_crtc_helper_set_config+0x6d8/0x988 [ 62.628906] [] drm_fb_helper_set_par+0x94/0x104 [ 62.628906] [] fbcon_init+0x424/0x57c [ 62.628906] [] visual_init+0xb8/0x118 [ 62.628906] [] take_over_console+0x238/0x384 [ 62.628906] [] fbcon_takeover+0x7c/0xdc [ 62.628906] [] notifier_call_chain+0x44/0x94 [ 62.628906] [] __blocking_notifier_call_chain+0x48/0x68 [ 62.628906] [] register_framebuffer+0x228/0x260 [ 62.628906] [] drm_fb_helper_single_fb_probe+0x260/0x314 [ 62.628906] [] drm_fb_helper_initial_config+0x200/0x234 [ 62.628906] [] radeon_fbdev_init+0xd4/0xf4 [ 62.628906] [] radeon_modeset_init+0x9bc/0xa18 [ 62.628906] [] radeon_driver_load_kms+0xdc/0x12c [ 62.628906] [] drm_get_pci_dev+0x148/0x238 [ 62.628906] [] local_pci_probe+0x5c/0xd0 [ 62.628906] [] work_for_cpu_fn+0x1c/0x30 [ 62.628906] [] process_one_work+0x274/0x3bc [ 62.628906] [] process_scheduled_works+0x24/0x44 [ 62.628906] [] worker_thread+0x31c/0x3f4 [ 62.628906] [] kthread+0x88/0x90 [ 62.628906] [] kernel_thread_helper+0x10/0x18 Signed-off-by: Huacai Chen Signed-off-by: Binbin Zhou Cc: Reviewed-by: Michel Dänzer Acked-by: Paul Menzel Signed-off-by: Dave Airlie Reported by: J.R. Oldroyd MFC after: 2 weeks --- sys/dev/drm2/drm_irq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/dev/drm2/drm_irq.c b/sys/dev/drm2/drm_irq.c index 4ab3de0..f79d46a 100644 --- a/sys/dev/drm2/drm_irq.c +++ b/sys/dev/drm2/drm_irq.c @@ -883,7 +883,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) */ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) { - /* vblank is not initialized (IRQ not installed ?) */ + /* vblank is not initialized (IRQ not installed ?), or has been freed */ if (!dev->num_crtcs) return; /* @@ -902,6 +902,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) void drm_vblank_post_modeset(struct drm_device *dev, int crtc) { + /* vblank is not initialized (IRQ not installed ?), or has been freed */ + if (!dev->num_crtcs) + return; if (dev->vblank_inmodeset[crtc]) { mtx_lock(&dev->vbl_lock); -- cgit v1.1