]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fb_set_suspend() must be called with the console semaphore held, which
authorAndrea Righi <arighi@develer.com>
Wed, 3 Aug 2011 00:52:39 +0000 (10:52 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 19 Aug 2011 02:31:15 +0000 (12:31 +1000)
means the code path coming in here will first take the console_lock() and
then call lock_fb_info().

However several framebuffer ioctl commands acquire these locks in reverse
order (lock_fb_info() and then console_lock()).  This gives rise to
potential AB-BA deadlock.

Fix this by changing the order of acquisition in the ioctl commands that
make use of console_lock().

Signed-off-by: Andrea Righi <arighi@develer.com>
Reported-by: Peter Nordström (Palm GBU) <peter.nordstrom@palm.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drivers/video/fbmem.c

index 5aac00eb1830c1724ed521f2bcc91693d9dbe646..ee2c060b034df0e02f1148a352689191c1c08d87 100644 (file)
@@ -1076,14 +1076,16 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
        case FBIOPUT_VSCREENINFO:
                if (copy_from_user(&var, argp, sizeof(var)))
                        return -EFAULT;
-               if (!lock_fb_info(info))
-                       return -ENODEV;
                console_lock();
+               if (!lock_fb_info(info)) {
+                       console_unlock();
+                       return -ENODEV;
+               }
                info->flags |= FBINFO_MISC_USEREVENT;
                ret = fb_set_var(info, &var);
                info->flags &= ~FBINFO_MISC_USEREVENT;
-               console_unlock();
                unlock_fb_info(info);
+               console_unlock();
                if (!ret && copy_to_user(argp, &var, sizeof(var)))
                        ret = -EFAULT;
                break;
@@ -1112,12 +1114,14 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
        case FBIOPAN_DISPLAY:
                if (copy_from_user(&var, argp, sizeof(var)))
                        return -EFAULT;
-               if (!lock_fb_info(info))
-                       return -ENODEV;
                console_lock();
+               if (!lock_fb_info(info)) {
+                       console_unlock();
+                       return -ENODEV;
+               }
                ret = fb_pan_display(info, &var);
-               console_unlock();
                unlock_fb_info(info);
+               console_unlock();
                if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
                        return -EFAULT;
                break;
@@ -1159,14 +1163,16 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
                unlock_fb_info(info);
                break;
        case FBIOBLANK:
-               if (!lock_fb_info(info))
-                       return -ENODEV;
                console_lock();
+               if (!lock_fb_info(info)) {
+                       console_unlock();
+                       return -ENODEV;
+               }
                info->flags |= FBINFO_MISC_USEREVENT;
                ret = fb_blank(info, arg);
                info->flags &= ~FBINFO_MISC_USEREVENT;
-               console_unlock();
                unlock_fb_info(info);
+               console_unlock();
                break;
        default:
                if (!lock_fb_info(info))