Skip to contentSkip to conversation

fbdev: fbcon: Fix KASAN slab-out-of-bounds read in rotated font buffer

PATCH In review Syed Tayyab Farooq 1 participant 2 messages Sep 23 – Nov 11

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fbdev: fbcon: Fix KASAN slab-out-of-bounds read in rotated font buffer

The root cause of this KASAN slab-out-of-bounds read is that fbcon fails to reallocate the rotated font buffer (par->rotated.buf) when the font character count changes but the font dimensions (width and height) remain the same.

When a user changes the font via ioctl(KDFONTOP), fbcon_do_set_font() is called. If the user first sets a 256-character font, enables rotation, and then sets a 512-character font with the exact same width and height, resize evaluates to false. The function then directly calls update_screen(vc). Notice that fbcon_do_set_font() never calls par->bitops->rotate_font() to update the rotated font buffer for the new font. As a result, par->rotated.buf remains sized for the old 256-character font.

When update_screen(vc) is called, it eventually reaches cw_putcs_aligned(), which attempts to read the glyphs from the rotated buffer. Since vc->vc_font.charcount is now 512, vc->vc_hi_font_mask is set, making charmask equal to 0x1ff (511). If the text buffer contains a character with an index >= 256, src will point out of bounds of the old par->rotated.buf (which only holds 256 glyphs). The subsequent read in __fb_pad_aligned_buffer() triggers the KASAN slab-out-of-bounds crash.

To fix this, fbcon_do_set_font() must call par->bitops->rotate_font() to update the rotated font buffer before calling vc_resize() or update_screen(). If vc_resize() fails and the old font is restored in the error path, rotate_font() must be called again to restore the rotated buffer.

This pattern of updating the rotated font buffer was previously established in fbcon_modechanged() by commit ef7656e85f1a ("fbdev: Fix out-of-bounds access when rotating console after font resize"). The fix applies this exact idiom to fbcon_do_set_font(). By placing it before vc_resize() and update_screen(), we ensure the buffer is correctly sized before any rendering occurs. Checking con_is_visible(vc) is also correct here, as hidden consoles will have their rotation state updated later via fbcon_switch() when they become visible.

Furthermore, by calling rotate_font() again in the err_out path, we ensure that if vc_resize() fails, the rotated buffer is restored to match the old vc->vc_font. Without this, restoring a 512-character font to a 256-character font on failure would leave the rotated buffer sized for 512 characters, which wastes memory; or worse, restoring a 256-character font to a 512-character font would leave the buffer too small, causing an out-of-bounds read later.

Fixes e4fc27618b75 ("[PATCH] fbcon: Console Rotation - Prepare fbcon for console rotation")
Assisted-by Gemini:gemini-3.6-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by [email protected]
---
 drivers/video/fbdev/core/fbcon.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/video/fbdev/core/fbcon.c +14 -0
index 01715873ea49..158b2f91d68e 100644
@@ -2432,6 +2432,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
 	else if (!vc->vc_hi_font_mask && charcount == 512)
 		set_vc_hi_font(vc, true);
 
+	if (con_is_visible(vc)) {
+		if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) {
+			par->rotate = FB_ROTATE_UR;
+			set_blitting_type(vc, info);
+		}
+	}
+
 	if (resize) {
 		int cols, rows;
 
@@ -2466,6 +2473,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
 	else if (!old_hi_font_mask && vc->vc_hi_font_mask)
 		set_vc_hi_font(vc, false);
 
+	if (con_is_visible(vc)) {
+		if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) {
+			par->rotate = FB_ROTATE_UR;
+			set_blitting_type(vc, info);
+		}
+	}
+
 	font_data_put(data);
 
 	return ret;
Signature · 1 line
2.43.0
#1 lore raw

Hi,

I wanted to follow up on this patch, if anyone has had a chance to review it.

Thanks,
Tayyab

Quoted 90 lines · Syed Tayyab Farooq

The root cause of this KASAN slab-out-of-bounds read is that fbcon fails to reallocate the rotated font buffer (par->rotated.buf) when the font character count changes but the font dimensions (width and height) remain the same.

When a user changes the font via ioctl(KDFONTOP), fbcon_do_set_font() is called. If the user first sets a 256-character font, enables rotation, and then sets a 512-character font with the exact same width and height, resize evaluates to false. The function then directly calls update_screen(vc). Notice that fbcon_do_set_font() never calls par->bitops->rotate_font() to update the rotated font buffer for the new font. As a result, par->rotated.buf remains sized for the old 256-character font.

When update_screen(vc) is called, it eventually reaches cw_putcs_aligned(), which attempts to read the glyphs from the rotated buffer. Since vc->vc_font.charcount is now 512, vc->vc_hi_font_mask is set, making charmask equal to 0x1ff (511). If the text buffer contains a character with an index >= 256, src will point out of bounds of the old par->rotated.buf (which only holds 256 glyphs). The subsequent read in __fb_pad_aligned_buffer() triggers the KASAN slab-out-of-bounds crash.

To fix this, fbcon_do_set_font() must call par->bitops->rotate_font() to update the rotated font buffer before calling vc_resize() or update_screen(). If vc_resize() fails and the old font is restored in the error path, rotate_font() must be called again to restore the rotated buffer.

This pattern of updating the rotated font buffer was previously established in fbcon_modechanged() by commit ef7656e85f1a ("fbdev: Fix out-of-bounds access when rotating console after font resize"). The fix applies this exact idiom to fbcon_do_set_font(). By placing it before vc_resize() and update_screen(), we ensure the buffer is correctly sized before any rendering occurs. Checking con_is_visible(vc) is also correct here, as hidden consoles will have their rotation state updated later via fbcon_switch() when they become visible.

Furthermore, by calling rotate_font() again in the err_out path, we ensure that if vc_resize() fails, the rotated buffer is restored to match the old vc->vc_font. Without this, restoring a 512-character font to a 256-character font on failure would leave the rotated buffer sized for 512 characters, which wastes memory; or worse, restoring a 256-character font to a 512-character font would leave the buffer too small, causing an out-of-bounds read later.

Fixes e4fc27618b75 ("[PATCH] fbcon: Console Rotation - Prepare fbcon for console rotation")
Assisted-by Gemini:gemini-3.6-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by [email protected]
---
 drivers/video/fbdev/core/fbcon.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/video/fbdev/core/fbcon.c +14 -1
index 01715873ea49..158b2f91d68e 100644
@@ -2432,6 +2432,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        else if (!vc->vc_hi_font_mask && charcount == 512)
                set_vc_hi_font(vc, true);
 
+       if (con_is_visible(vc)) {
+               if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) {
+                       par->rotate = FB_ROTATE_UR;
+                       set_blitting_type(vc, info);
+               }
+       }
+
        if (resize) {
                int cols, rows;
 
@@ -2466,6 +2473,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        else if (!old_hi_font_mask && vc->vc_hi_font_mask)
                set_vc_hi_font(vc, false);
 
+       if (con_is_visible(vc)) {
+               if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) {
+                       par->rotate = FB_ROTATE_UR;
+                       set_blitting_type(vc, info);
+               }
+       }
+
        font_data_put(data);
 
        return ret;
--

2.43.0