Skip to content

Commit 086ff84

Browse files
committed
Merge tag 'for-5.19/fbdev-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev
Pull fbdev fixes from Helge Deller: - fbcon now prevents switching to screen resolutions which are smaller than the font size, and prevents enabling a font which is bigger than the current screen resolution. This fixes vmalloc-out-of-bounds accesses found by KASAN. - Guiling Deng fixed a bug where the centered fbdev logo wasn't displayed correctly if the screen size matched the logo size. - Hsin-Yi Wang provided a patch to include errno.h to fix build when CONFIG_OF isn't enabled. * tag 'for-5.19/fbdev-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev: fbcon: Use fbcon_info_from_console() in fbcon_modechange_possible() fbmem: Check virtual screen sizes in fb_set_var() fbcon: Prevent that screen size is smaller than font size fbcon: Disallow setting font bigger than screen size video: of_display_timing.h: include errno.h fbdev: fbmem: Fix logo center image dx issue
2 parents e8a4e1c + 53a6e66 commit 086ff84

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

drivers/video/fbdev/core/fbcon.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,6 +2469,11 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
24692469
if (charcount != 256 && charcount != 512)
24702470
return -EINVAL;
24712471

2472+
/* font bigger than screen resolution ? */
2473+
if (w > FBCON_SWAP(info->var.rotate, info->var.xres, info->var.yres) ||
2474+
h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres))
2475+
return -EINVAL;
2476+
24722477
/* Make sure drawing engine can handle the font */
24732478
if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
24742479
!(info->pixmap.blit_y & (1 << (font->height - 1))))
@@ -2731,6 +2736,34 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
27312736
}
27322737
EXPORT_SYMBOL(fbcon_update_vcs);
27332738

2739+
/* let fbcon check if it supports a new screen resolution */
2740+
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
2741+
{
2742+
struct fbcon_ops *ops = info->fbcon_par;
2743+
struct vc_data *vc;
2744+
unsigned int i;
2745+
2746+
WARN_CONSOLE_UNLOCKED();
2747+
2748+
if (!ops)
2749+
return 0;
2750+
2751+
/* prevent setting a screen size which is smaller than font size */
2752+
for (i = first_fb_vc; i <= last_fb_vc; i++) {
2753+
vc = vc_cons[i].d;
2754+
if (!vc || vc->vc_mode != KD_TEXT ||
2755+
fbcon_info_from_console(i) != info)
2756+
continue;
2757+
2758+
if (vc->vc_font.width > FBCON_SWAP(var->rotate, var->xres, var->yres) ||
2759+
vc->vc_font.height > FBCON_SWAP(var->rotate, var->yres, var->xres))
2760+
return -EINVAL;
2761+
}
2762+
2763+
return 0;
2764+
}
2765+
EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
2766+
27342767
int fbcon_mode_deleted(struct fb_info *info,
27352768
struct fb_videomode *mode)
27362769
{

drivers/video/fbdev/core/fbmem.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
511511

512512
while (n && (n * (logo->width + 8) - 8 > xres))
513513
--n;
514-
image.dx = (xres - n * (logo->width + 8) - 8) / 2;
514+
image.dx = (xres - (n * (logo->width + 8) - 8)) / 2;
515515
image.dy = y ?: (yres - logo->height) / 2;
516516
} else {
517517
image.dx = 0;
@@ -1017,6 +1017,16 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
10171017
if (ret)
10181018
return ret;
10191019

1020+
/* verify that virtual resolution >= physical resolution */
1021+
if (var->xres_virtual < var->xres ||
1022+
var->yres_virtual < var->yres) {
1023+
pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n",
1024+
info->fix.id,
1025+
var->xres_virtual, var->yres_virtual,
1026+
var->xres, var->yres);
1027+
return -EINVAL;
1028+
}
1029+
10201030
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
10211031
return 0;
10221032

@@ -1107,7 +1117,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
11071117
return -EFAULT;
11081118
console_lock();
11091119
lock_fb_info(info);
1110-
ret = fb_set_var(info, &var);
1120+
ret = fbcon_modechange_possible(info, &var);
1121+
if (!ret)
1122+
ret = fb_set_var(info, &var);
11111123
if (!ret)
11121124
fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
11131125
unlock_fb_info(info);

include/linux/fbcon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void fbcon_new_modelist(struct fb_info *info);
1515
void fbcon_get_requirement(struct fb_info *info,
1616
struct fb_blit_caps *caps);
1717
void fbcon_fb_blanked(struct fb_info *info, int blank);
18+
int fbcon_modechange_possible(struct fb_info *info,
19+
struct fb_var_screeninfo *var);
1820
void fbcon_update_vcs(struct fb_info *info, bool all);
1921
void fbcon_remap_all(struct fb_info *info);
2022
int fbcon_set_con2fb_map_ioctl(void __user *argp);
@@ -33,6 +35,8 @@ static inline void fbcon_new_modelist(struct fb_info *info) {}
3335
static inline void fbcon_get_requirement(struct fb_info *info,
3436
struct fb_blit_caps *caps) {}
3537
static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
38+
static inline int fbcon_modechange_possible(struct fb_info *info,
39+
struct fb_var_screeninfo *var) { return 0; }
3640
static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
3741
static inline void fbcon_remap_all(struct fb_info *info) {}
3842
static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }

include/video/of_display_timing.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef __LINUX_OF_DISPLAY_TIMING_H
99
#define __LINUX_OF_DISPLAY_TIMING_H
1010

11+
#include <linux/errno.h>
12+
1113
struct device_node;
1214
struct display_timing;
1315
struct display_timings;

0 commit comments

Comments
 (0)