fbcon: Prevent that screen size is smaller than font size

commit e64242caef18b4a5840b0e7a9bff37abd4f4f933 upstream.

We need to prevent that users configure a screen size which is smaller than the
currently selected font size. Otherwise rendering chars on the screen will
access memory outside the graphics memory region.

This patch adds a new function fbcon_modechange_possible() which
implements this check and which later may be extended with other checks
if necessary.  The new function is called from the FBIOPUT_VSCREENINFO
ioctl handler in fbmem.c, which will return -EINVAL if userspace asked
for a too small screen size.

Signed-off-by: Helge Deller <deller@gmx.de>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: stable@vger.kernel.org # v5.4+
Signed-off-by: Hugo SIMELIERE <hsimeliere.opensource@witekio.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Helge Deller
2024-08-29 18:14:03 +02:00
committed by Greg Kroah-Hartman
parent 9e235ce6fa
commit 54eaaac622
3 changed files with 38 additions and 3 deletions

View File

@@ -2734,6 +2734,34 @@ static void fbcon_set_all_vcs(struct fb_info *info)
fbcon_modechanged(info);
}
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
{
struct fbcon_ops *ops = info->fbcon_par;
struct vc_data *vc;
unsigned int i;
WARN_CONSOLE_UNLOCKED();
if (!ops)
return 0;
/* prevent setting a screen size which is smaller than font size */
for (i = first_fb_vc; i <= last_fb_vc; i++) {
vc = vc_cons[i].d;
if (!vc || vc->vc_mode != KD_TEXT ||
registered_fb[con2fb_map[i]] != info)
continue;
if (vc->vc_font.width > FBCON_SWAP(var->rotate, var->xres, var->yres) ||
vc->vc_font.height > FBCON_SWAP(var->rotate, var->yres, var->xres))
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
static int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
{

View File

@@ -1121,9 +1121,12 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
console_unlock();
return -ENODEV;
}
ret = fbcon_modechange_possible(info, &var);
if (!ret) {
info->flags |= FBINFO_MISC_USEREVENT;
ret = fb_set_var(info, &var);
info->flags &= ~FBINFO_MISC_USEREVENT;
}
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))

View File

@@ -4,9 +4,13 @@
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
void __init fb_console_init(void);
void __exit fb_console_exit(void);
int fbcon_modechange_possible(struct fb_info *info,
struct fb_var_screeninfo *var);
#else
static inline void fb_console_init(void) {}
static inline void fb_console_exit(void) {}
static inline int fbcon_modechange_possible(struct fb_info *info,
struct fb_var_screeninfo *var) { return 0; }
#endif
#endif /* _LINUX_FBCON_H */