Kernel hacking – Crash in the framebuffer

I had a play with the kenel framebuffer, and managed to lock up my machine:

In one thread:
[  701.790000] c3 [] (mutex_lock+0xc/0x24) from [] (lock_fb_info+0x14/0x38)
[  701.790000] c3 [] (lock_fb_info+0x14/0x38) from [] (fbcon_blank+0x234/0x260)
[  701.790000] c3 [] (fbcon_blank+0x234/0x260) from [] (do_blank_screen+0x1d0/0x27c)
[  701.790000] c3 [] (do_blank_screen+0x1d0/0x27c) from [] (console_callback+0x8c/0x140)
[  701.790000] c3 [] (console_callback+0x8c/0x140) from [] (process_one_work+0x12c/0x3d0)
[  701.790000] c3 [] (process_one_work+0x12c/0x3d0) from [] (worker_thread+0x190/0x3dc)
[  701.790000] c3 [] (worker_thread+0x190/0x3dc) from [] (kthread+0x90/0x94)
[  701.790000] c3 [] (kthread+0x90/0x94) from [] (kernel_thread_exit+0x0/0x8)

In another thread:
[  701.790000] c3 SurfaceFlinger  D 02517c7c     0   258      1 0x00000001
[  701.790000] c3 [] (__schedule+0x214/0x6f8) from [] (schedule_timeout+0x180/0x1d0)
[  701.790000] c3 [] (schedule_timeout+0x180/0x1d0) from [] (__down+0x78/0xac)
[  701.790000] c3 [] (__down+0x78/0xac) from [] (down+0x44/0x4c)
[  701.790000] c3 [] (down+0x44/0x4c) from [] (console_lock+0x2c/0x60)
[  701.790000] c3 [] (console_lock+0x2c/0x60) from [] (do_fb_ioctl+0x394/0x450)
[  701.790000] c3 [] (do_fb_ioctl+0x394/0x450) from [] (do_vfs_ioctl+0x84/0x4ec)
[  701.790000] c3 [] (do_vfs_ioctl+0x84/0x4ec) from [] (sys_ioctl+0x38/0x60)

So in the first thread, we get console_lock (in console_callback) and then lock_fb_info.

In the second thread we get lock_fb_info (in do_fb_ioctl) and then console_lock.
I came up with a pretty trivial patch for this:
Subject: [PATCH] Fix deadlock between fb_info and console.  Do not lock
 fb_info when calling sending the FB_EVENT_CONBLANK

In fbmem.c, the semantics are that we acquire the lock_fb_info first,
and then console_lock.  However when fbcon.c fbcon_generic_blank() is
called, the console lock could already be held.  Locking fb_info can
thus cause a deadlock.

fbmem.c sends the FB_EVENT_BLANK without locking lock_fb_info first, so
this change introduces similar behaviour.
---
 drivers/video/console/fbcon.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 6b4fb5c..8546441 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2333,13 +2333,9 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
         vc->vc_video_erase_char = oldc;
     }
 
-
-    if (!lock_fb_info(info))
-        return;
     event.info = info;
     event.data = ␣
     fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
-    unlock_fb_info(info);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
-- 
1.8.1.2

I passed the patch onto the framebuffer developers, but they weren't very interested because this whole code should be going away at sometime.