mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
fbdev: fbcon: fix out-of-bounds read in err_out of fbcon_do_set_font()
[ Upstream commit8fdc8c2057] When fbcon_do_set_font() fails (e.g., due to a memory allocation failure inside vc_resize() under heavy memory pressure), it jumps to the `err_out` label to roll back the console state. However, the current rollback logic forgets to restore the `hi_font` state, leading to a severe state machine corruption. Earlier in the function, `set_vc_hi_font()` might be called to change `vc->vc_hi_font_mask` and mutate the screen buffer. If `vc_resize()` subsequently fails, the `err_out` path restores `vc_font.charcount` but entirely skips rolling back the `vc_hi_font_mask` and the screen buffer. This mismatch leaves the terminal in a desynchronized state. Because `vc_hi_font_mask` remains set, the VT subsystem will still accept character indices greater than 255 from userspace and write them to the screen buffer. Subsequent rendering calls (e.g., `fbcon_putcs()`) will then use these inflated indices to access the reverted, 256-character font array, leading to a deterministic out-of-bounds read and potential kernel memory disclosure. Fix this by adding the missing rollback logic for the `hi_font` mask and screen buffer in the error path. Fixes:a5a923038d("fbdev: fbcon: Properly revert changes when vc_resize() failed") Cc: stable@vger.kernel.org Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Helge Deller <deller@gmx.de> [ Adjust context ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
406c28af75
commit
076b1aa65f
@@ -2422,6 +2422,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
||||
struct fbcon_display *p = &fb_display[vc->vc_num];
|
||||
int resize, ret, old_userfont, old_width, old_height, old_charcount;
|
||||
u8 *old_data = vc->vc_font.data;
|
||||
unsigned short old_hi_font_mask = vc->vc_hi_font_mask;
|
||||
|
||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
||||
vc->vc_font.data = (void *)(p->fontdata = data);
|
||||
@@ -2475,6 +2476,12 @@ err_out:
|
||||
vc->vc_font.height = old_height;
|
||||
vc->vc_font.charcount = old_charcount;
|
||||
|
||||
/* Restore the hi_font state and screen buffer */
|
||||
if (old_hi_font_mask && !vc->vc_hi_font_mask)
|
||||
set_vc_hi_font(vc, true);
|
||||
else if (!old_hi_font_mask && vc->vc_hi_font_mask)
|
||||
set_vc_hi_font(vc, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user