refer to https://lore.kernel.org/all/20220706150253.2186-1-deller@gmx.de/ 3 patches are provided to fix CVE-2021-33655 (When sending malicous data to kernel by ioctl cmd FBIOPUT_VSCREENINFO,kernel will write memory out of bounds. https://nvd.nist.gov/vuln/detail/CVE-2021-33655) in mainline.
The problem exists in 4.9
static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) fb_set_var(info, &var); fb_notifier_call_chain(evnt, &event); // evnt = FB_EVENT_MODE_CHANGE
static int fbcon_event_notify(struct notifier_block *self, unsigned long action, void *data) fbcon_modechanged(info); updatescrollmode(p, info, vc); ... p->vrows = vyres/fh; if (yres > (fh * (vc->vc_rows + 1))) p->vrows -= (yres - (fh * vc->vc_rows)) / fh; if ((yres % fh) && (vyres % fh < yres % fh)) p->vrows--; [1] [1]: p->vrows could be -1, like what CVE-2021-33655 described.
To fix it, backport the three patches.
d48de54a9dab ("printk: Export is_console_locked") should also be backported to avoid building failed if CONFIG_FB = m.
Hans de Goede (1): printk: Export is_console_locked
Helge Deller (3): fbmem: Check virtual screen sizes in fb_set_var() fbcon: Disallow setting font bigger than screen size fbcon: Prevent that screen size is smaller than font size
drivers/video/console/fbcon.c | 33 ++++++++++++++++++++++++++++++++ drivers/video/fbdev/core/fbmem.c | 20 ++++++++++++++++--- include/linux/fbcon.h | 12 ++++++++++++ kernel/printk/printk.c | 1 + 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 include/linux/fbcon.h
From: Hans de Goede hdegoede@redhat.com
commit d48de54a9dab5370edd2e991f78cc7996cf5483e upstream
This is a preparation patch for adding a number of WARN_CONSOLE_UNLOCKED() calls to the fbcon code, which may be built as a module (event though usually it is not).
Acked-by: Steven Rostedt (VMware) rostedt@goodmis.org Acked-by: Sergey Senozhatsky sergey.senozhatsky@gmail.com Acked-by: Petr Mladek pmladek@suse.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com Signed-off-by: Chen Jun chenjun102@huawei.com --- kernel/printk/printk.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index f1f115b3ee01..c3ae4e17d69d 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2221,6 +2221,7 @@ int is_console_locked(void) { return console_locked; } +EXPORT_SYMBOL(is_console_locked);
/* * Check if we have any console that is capable of printing while cpu is
From: Helge Deller deller@gmx.de
commit 6c11df58fd1ac0aefcb3b227f72769272b939e56 upstream.
Verify that the fbdev or drm driver correctly adjusted the virtual screen sizes. On failure report the failing driver and reject the screen size change.
Signed-off-by: Helge Deller deller@gmx.de Reviewed-by: Geert Uytterhoeven geert@linux-m68k.org Cc: stable@vger.kernel.org # v5.4+ Link: https://lore.kernel.org/all/20220706150253.2186-1-deller@gmx.de/ [sudip: adjust context] Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/video/fbdev/core/fbmem.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index e83b7ca500b7..90d918c78f04 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1017,6 +1017,16 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) if (ret) goto done;
+ /* verify that virtual resolution >= physical resolution */ + if (var->xres_virtual < var->xres || + var->yres_virtual < var->yres) { + pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n", + info->fix.id, + var->xres_virtual, var->yres_virtual, + var->xres, var->yres); + return -EINVAL; + } + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { struct fb_var_screeninfo old_var; struct fb_videomode mode;
From: Helge Deller deller@gmx.de
commit 65a01e601dbba8b7a51a2677811f70f783766682 upstream.
Prevent that users set a font size which is bigger than the physical screen. It's unlikely this may happen (because screens are usually much larger than the fonts and each font char is limited to 32x32 pixels), but it may happen on smaller screens/LCD displays.
Signed-off-by: Helge Deller deller@gmx.de Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Reviewed-by: Geert Uytterhoeven geert@linux-m68k.org Cc: stable@vger.kernel.org # v4.14+ Link: https://lore.kernel.org/all/20220706150253.2186-1-deller@gmx.de/ Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/video/console/fbcon.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 510bc3f51dcc..e9eb8aaa2040 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2428,6 +2428,11 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne if (charcount != 256 && charcount != 512) return -EINVAL;
+ /* font bigger than screen resolution ? */ + if (w > FBCON_SWAP(info->var.rotate, info->var.xres, info->var.yres) || + h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) + return -EINVAL; + /* Make sure drawing engine can handle the font */ if (!(info->pixmap.blit_x & (1 << (font->width - 1))) || !(info->pixmap.blit_y & (1 << (font->height - 1))))
From: Helge Deller deller@gmx.de
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+ Link: https://lore.kernel.org/all/20220706150253.2186-1-deller@gmx.de/ [sudip: adjust context] Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/video/console/fbcon.c | 28 ++++++++++++++++++++++++++++ drivers/video/fbdev/core/fbmem.c | 10 +++++++--- include/linux/fbcon.h | 12 ++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 include/linux/fbcon.h
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e9eb8aaa2040..2097670b22f7 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2689,6 +2689,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) { diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 90d918c78f04..b13f6f02633d 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -32,6 +32,7 @@ #include <linux/device.h> #include <linux/efi.h> #include <linux/fb.h> +#include <linux/fbcon.h> #include <linux/overflow.h>
#include <asm/fb.h> @@ -1142,9 +1143,12 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, console_unlock(); return -ENODEV; } - info->flags |= FBINFO_MISC_USEREVENT; - ret = fb_set_var(info, &var); - info->flags &= ~FBINFO_MISC_USEREVENT; + 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))) diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h new file mode 100644 index 000000000000..f3da28242ef4 --- /dev/null +++ b/include/linux/fbcon.h @@ -0,0 +1,12 @@ +#ifndef _LINUX_FBCON_H +#define _LINUX_FBCON_H + +#ifdef CONFIG_FRAMEBUFFER_CONSOLE +int fbcon_modechange_possible(struct fb_info *info, + struct fb_var_screeninfo *var); +#else +static inline int fbcon_modechange_possible(struct fb_info *info, + struct fb_var_screeninfo *var) { return 0; } +#endif + +#endif /* _LINUX_FBCON_H */
linux-stable-mirror@lists.linaro.org