fb_set_var() can delete a mode from info->modelist when userspace
passes FB_ACTIVATE_INV_MODE through FBIOPUT_VSCREENINFO. The code
checks that the mode being deleted is not the current info->var and
that fbcon is not using it, but it does not check fb_info->mode.

fb_info->mode may still point into the modelist entry being deleted.
If the entry is freed, later mode sysfs reads through show_mode() can
dereference a stale pointer.

Clear fb_info->mode before calling fb_delete_videomode() when it
matches the mode being removed.

Cc: [email protected]
Signed-off-by: Melbin K Mathew <[email protected]>
---
 drivers/video/fbdev/core/fbmem.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 2f1c56e5a7..c8aa163b0e 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -246,8 +246,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo 
*var)
                ret = fb_mode_is_equal(&mode1, &mode2);
                if (!ret) {
                        ret = fbcon_mode_deleted(info, &mode1);
-                       if (!ret)
+                       if (!ret) {
+                               if (info->mode && fb_mode_is_equal(info->mode, 
&mode1))
+                                       info->mode = NULL;
                                fb_delete_videomode(&mode1, &info->modelist);
+                       }
                }
 
                return ret ? -EINVAL : 0;
-- 
2.39.5

Reply via email to