Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54eaaac6 authored by Helge Deller's avatar Helge Deller Committed by Greg Kroah-Hartman
Browse files

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: default avatarHelge Deller <deller@gmx.de>
Reviewed-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Cc: stable@vger.kernel.org # v5.4+
Signed-off-by: default avatarHugo SIMELIERE <hsimeliere.opensource@witekio.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9e235ce6
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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)
{
+6 −3
Original line number Diff line number Diff line
@@ -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)))
+4 −0
Original line number Diff line number Diff line
@@ -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 */