This is a regressoin introduced in b07db3958485 ("fbcon: Ditch error handling for con2fb_release_oldinfo"). I failed to realize that the if (!err) checks and therefore flattening the control flow due to con2fb_release_oldinfo() (which was impossible) wasn't correct, because con2fb_acquire_newinfo() could fail.
Fix this with an early return statement.
Note that there's still a difference compared to the orginal state of the code, the below lines are now also skipped on error:
if (!search_fb_in_map(info_idx)) info_idx = newidx;
These are only needed when we've actually thrown out an old fb_info from the console mappings, which only happens later on.
Also move the fbcon_add_cursor_work() call into the same if block, it's all protected by console_lock so doesn't matter when we set up the blinking cursor delayed work anyway. This further simplifies the control flow and allows us to ditch the found local variable.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Fixes: b07db3958485 ("fbcon: Ditch error handling for con2fb_release_oldinfo") Cc: Thomas Zimmermann tzimmermann@suse.de Cc: Sam Ravnborg sam@ravnborg.org Cc: Xingyuan Mo hdthky0@gmail.com Cc: Thomas Zimmermann tzimmermann@suse.de Cc: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.19+ --- drivers/video/fbdev/core/fbcon.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 0a2c47df01f4..52f6ce8e794a 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -823,7 +823,7 @@ static int set_con2fb_map(int unit, int newidx, int user) int oldidx = con2fb_map[unit]; struct fb_info *info = fbcon_registered_fb[newidx]; struct fb_info *oldinfo = NULL; - int found, err = 0, show_logo; + int err = 0, show_logo;
WARN_CONSOLE_UNLOCKED();
@@ -841,26 +841,25 @@ static int set_con2fb_map(int unit, int newidx, int user) if (oldidx != -1) oldinfo = fbcon_registered_fb[oldidx];
- found = search_fb_in_map(newidx); - - if (!err && !found) { + if (!search_fb_in_map(newidx)) { err = con2fb_acquire_newinfo(vc, info, unit); - if (!err) - con2fb_map[unit] = newidx; + if (err) + return err; + + con2fb_map[unit] = newidx; + fbcon_add_cursor_work(info); }
/* * If old fb is not mapped to any of the consoles, * fbcon should release it. */ - if (!err && oldinfo && !search_fb_in_map(oldidx)) + if (oldinfo && !search_fb_in_map(oldidx)) con2fb_release_oldinfo(vc, oldinfo, info);
show_logo = (fg_console == 0 && !user && logo_shown != FBCON_LOGO_DONTSHOW);
- if (!found) - fbcon_add_cursor_work(info); con2fb_map_boot[unit] = newidx; con2fb_init_display(vc, info, unit, show_logo);
I got really badly confused in d443d9386472 ("fbcon: move more common code into fb_open()") because we set the con2fb_map before the failure points, which didn't look good.
But in trying to fix that I moved the assignment into the wrong path - we need to do it for _all_ vc we take over, not just the first one (which additionally requires the call to con2fb_acquire_newinfo).
I've figured this out because of a KASAN bug report, where the fbcon_registered_fb and fbcon_display arrays went out of sync in fbcon_mode_deleted() because the con2fb_map pointed at the old fb_info, but the modes and everything was updated for the new one.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Fixes: d443d9386472 ("fbcon: move more common code into fb_open()") Reported-by: Xingyuan Mo hdthky0@gmail.com Cc: Thomas Zimmermann tzimmermann@suse.de Cc: Sam Ravnborg sam@ravnborg.org Cc: Xingyuan Mo hdthky0@gmail.com Cc: Thomas Zimmermann tzimmermann@suse.de Cc: Helge Deller deller@gmx.de Cc: stable@vger.kernel.org # v5.19+ --- drivers/video/fbdev/core/fbcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 52f6ce8e794a..eb565a10e5cd 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -846,10 +846,11 @@ static int set_con2fb_map(int unit, int newidx, int user) if (err) return err;
- con2fb_map[unit] = newidx; fbcon_add_cursor_work(info); }
+ con2fb_map[unit] = newidx; + /* * If old fb is not mapped to any of the consoles, * fbcon should release it.
linux-stable-mirror@lists.linaro.org