Skip to content

Commit ae12878

Browse files
committed
fbcon: don't lose the console font across generic->chip driver switch
If grub2 loads efifb/vesafb, then when systemd starts it can set the console font on that framebuffer device, however when we then load the native KMS driver, the first thing it does is tear down the generic framebuffer driver. The thing is the generic code is doing the right thing, it frees the font because otherwise it would leak memory. However we can assume that if you are removing the generic firmware driver (vesa/efi/offb), that a new driver *should* be loading soon after, so we effectively leak the font. However the old code left a dangling pointer in vc->vc_font.data and we can now reuse that dangling pointer to load the font into the new driver, now that we aren't freeing it. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=892340 Cc: Kay Sievers <kay.sievers@vrfy.org> Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
1 parent 2a24830 commit ae12878

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

drivers/video/console/fbcon.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ static const char *fbcon_startup(void)
990990
}
991991

992992
/* Setup default font */
993-
if (!p->fontdata) {
993+
if (!p->fontdata && !vc->vc_font.data) {
994994
if (!fontname[0] || !(font = find_font(fontname)))
995995
font = get_default_font(info->var.xres,
996996
info->var.yres,
@@ -1000,6 +1000,8 @@ static const char *fbcon_startup(void)
10001000
vc->vc_font.height = font->height;
10011001
vc->vc_font.data = (void *)(p->fontdata = font->data);
10021002
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
1003+
} else {
1004+
p->fontdata = vc->vc_font.data;
10031005
}
10041006

10051007
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
@@ -1159,9 +1161,9 @@ static void fbcon_init(struct vc_data *vc, int init)
11591161
ops->p = &fb_display[fg_console];
11601162
}
11611163

1162-
static void fbcon_free_font(struct display *p)
1164+
static void fbcon_free_font(struct display *p, bool freefont)
11631165
{
1164-
if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
1166+
if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
11651167
kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
11661168
p->fontdata = NULL;
11671169
p->userfont = 0;
@@ -1173,8 +1175,8 @@ static void fbcon_deinit(struct vc_data *vc)
11731175
struct fb_info *info;
11741176
struct fbcon_ops *ops;
11751177
int idx;
1178+
bool free_font = true;
11761179

1177-
fbcon_free_font(p);
11781180
idx = con2fb_map[vc->vc_num];
11791181

11801182
if (idx == -1)
@@ -1185,6 +1187,8 @@ static void fbcon_deinit(struct vc_data *vc)
11851187
if (!info)
11861188
goto finished;
11871189

1190+
if (info->flags & FBINFO_MISC_FIRMWARE)
1191+
free_font = false;
11881192
ops = info->fbcon_par;
11891193

11901194
if (!ops)
@@ -1196,6 +1200,8 @@ static void fbcon_deinit(struct vc_data *vc)
11961200
ops->flags &= ~FBCON_FLAGS_INIT;
11971201
finished:
11981202

1203+
fbcon_free_font(p, free_font);
1204+
11991205
if (!con_is_bound(&fb_con))
12001206
fbcon_exit();
12011207

0 commit comments

Comments
 (0)