]>
Commit | Line | Data |
---|---|---|
21e66c7d GKH |
1 | From b7ea85a4fed37835eec78a7be3039c8dc22b8178 Mon Sep 17 00:00:00 2001 |
2 | From: Huacai Chen <chenhc@lemote.com> | |
3 | Date: Tue, 21 May 2013 06:23:43 +0000 | |
4 | Subject: drm: fix a use-after-free when GPU acceleration disabled | |
5 | ||
6 | From: Huacai Chen <chenhc@lemote.com> | |
7 | ||
8 | commit b7ea85a4fed37835eec78a7be3039c8dc22b8178 upstream. | |
9 | ||
10 | When GPU acceleration is disabled, drm_vblank_cleanup() will free the | |
11 | vblank-related data, such as vblank_refcount, vblank_inmodeset, etc. | |
12 | But we found that drm_vblank_post_modeset() may be called after the | |
13 | cleanup, which use vblank_refcount and vblank_inmodeset. And this will | |
14 | cause a kernel panic. | |
15 | ||
16 | Fix this by return immediately if dev->num_crtcs is zero. This is the | |
17 | same thing that drm_vblank_pre_modeset() does. | |
18 | ||
19 | Call trace of a drm_vblank_post_modeset() after drm_vblank_cleanup(): | |
20 | [ 62.628906] [<ffffffff804868d0>] drm_vblank_post_modeset+0x34/0xb4 | |
21 | [ 62.628906] [<ffffffff804c7008>] atombios_crtc_dpms+0xb4/0x174 | |
22 | [ 62.628906] [<ffffffff804c70e0>] atombios_crtc_commit+0x18/0x38 | |
23 | [ 62.628906] [<ffffffff8047f038>] drm_crtc_helper_set_mode+0x304/0x3cc | |
24 | [ 62.628906] [<ffffffff8047f92c>] drm_crtc_helper_set_config+0x6d8/0x988 | |
25 | [ 62.628906] [<ffffffff8047dd40>] drm_fb_helper_set_par+0x94/0x104 | |
26 | [ 62.628906] [<ffffffff80439d14>] fbcon_init+0x424/0x57c | |
27 | [ 62.628906] [<ffffffff8046a638>] visual_init+0xb8/0x118 | |
28 | [ 62.628906] [<ffffffff8046b9f8>] take_over_console+0x238/0x384 | |
29 | [ 62.628906] [<ffffffff80436df8>] fbcon_takeover+0x7c/0xdc | |
30 | [ 62.628906] [<ffffffff8024fa20>] notifier_call_chain+0x44/0x94 | |
31 | [ 62.628906] [<ffffffff8024fcbc>] __blocking_notifier_call_chain+0x48/0x68 | |
32 | [ 62.628906] [<ffffffff8042d990>] register_framebuffer+0x228/0x260 | |
33 | [ 62.628906] [<ffffffff8047e010>] drm_fb_helper_single_fb_probe+0x260/0x314 | |
34 | [ 62.628906] [<ffffffff8047e2c4>] drm_fb_helper_initial_config+0x200/0x234 | |
35 | [ 62.628906] [<ffffffff804e5560>] radeon_fbdev_init+0xd4/0xf4 | |
36 | [ 62.628906] [<ffffffff804e0e08>] radeon_modeset_init+0x9bc/0xa18 | |
37 | [ 62.628906] [<ffffffff804bfc14>] radeon_driver_load_kms+0xdc/0x12c | |
38 | [ 62.628906] [<ffffffff8048b548>] drm_get_pci_dev+0x148/0x238 | |
39 | [ 62.628906] [<ffffffff80423564>] local_pci_probe+0x5c/0xd0 | |
40 | [ 62.628906] [<ffffffff80241ac4>] work_for_cpu_fn+0x1c/0x30 | |
41 | [ 62.628906] [<ffffffff802427c8>] process_one_work+0x274/0x3bc | |
42 | [ 62.628906] [<ffffffff80242934>] process_scheduled_works+0x24/0x44 | |
43 | [ 62.628906] [<ffffffff8024515c>] worker_thread+0x31c/0x3f4 | |
44 | [ 62.628906] [<ffffffff802497a8>] kthread+0x88/0x90 | |
45 | [ 62.628906] [<ffffffff80206794>] kernel_thread_helper+0x10/0x18 | |
46 | ||
47 | Signed-off-by: Huacai Chen <chenhc@lemote.com> | |
48 | Signed-off-by: Binbin Zhou <zhoubb@lemote.com> | |
49 | Reviewed-by: Michel Dänzer <michel.daenzer@amd.com> | |
50 | Acked-by: Paul Menzel <paulepanter@users.sourceforge.net> | |
51 | Signed-off-by: Dave Airlie <airlied@gmail.com> | |
52 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
53 | ||
54 | --- | |
55 | drivers/gpu/drm/drm_irq.c | 6 +++++- | |
56 | 1 file changed, 5 insertions(+), 1 deletion(-) | |
57 | ||
58 | --- a/drivers/gpu/drm/drm_irq.c | |
59 | +++ b/drivers/gpu/drm/drm_irq.c | |
60 | @@ -981,7 +981,7 @@ EXPORT_SYMBOL(drm_vblank_off); | |
61 | */ | |
62 | void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |
63 | { | |
64 | - /* vblank is not initialized (IRQ not installed ?) */ | |
65 | + /* vblank is not initialized (IRQ not installed ?), or has been freed */ | |
66 | if (!dev->num_crtcs) | |
67 | return; | |
68 | /* | |
69 | @@ -1003,6 +1003,10 @@ void drm_vblank_post_modeset(struct drm_ | |
70 | { | |
71 | unsigned long irqflags; | |
72 | ||
73 | + /* vblank is not initialized (IRQ not installed ?), or has been freed */ | |
74 | + if (!dev->num_crtcs) | |
75 | + return; | |
76 | + | |
77 | if (dev->vblank_inmodeset[crtc]) { | |
78 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | |
79 | dev->vblank_disable_allowed = 1; |