Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vt: discard stale unicode buffer on alt screen exit after resize

When enter_alt_screen() saves vc_uni_lines into vc_saved_uni_lines and
sets vc_uni_lines to NULL, a subsequent console resize via vc_do_resize()
skips reallocating the unicode buffer because vc_uni_lines is NULL.
However, vc_saved_uni_lines still points to the old buffer allocated for
the original dimensions.

When leave_alt_screen() later restores vc_saved_uni_lines, the buffer
dimensions no longer match vc_rows/vc_cols. Any operation that iterates
over the unicode buffer using the current dimensions (e.g. csi_J clearing
the screen) will access memory out of bounds, causing a kernel oops:

BUG: unable to handle page fault for address: 0x0000002000000020
RIP: 0010:csi_J+0x133/0x2d0

The faulting address 0x0000002000000020 is two adjacent u32 space
characters (0x20) interpreted as a pointer, read from the row data area
past the end of the 25-entry pointer array in a buffer allocated for
80x25 but accessed with 240x67 dimensions.

Fix this by checking whether the console dimensions changed while in the
alternate screen. If they did, free the stale saved buffer instead of
restoring it. The unicode screen will be lazily rebuilt via
vc_uniscr_check() when next needed.

Fixes: 5eb608319bb5 ("vt: save/restore unicode screen buffer for alternate screen")
Cc: stable <stable@kernel.org>
Tested-by: Liav Mordouch <liavmordouch@gmail.com>
Signed-off-by: Liav Mordouch <liavmordouch@gmail.com>
Reviewed-by: Nicolas Pitre <nico@fluxnic.net>
Link: https://patch.msgid.link/20260327170204.29706-1-liavmordouch@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Liav Mordouch and committed by
Greg Kroah-Hartman
40014493 c3692998

+13 -1
+13 -1
drivers/tty/vt/vt.c
··· 1901 1901 unsigned int rows = min(vc->vc_saved_rows, vc->vc_rows); 1902 1902 unsigned int cols = min(vc->vc_saved_cols, vc->vc_cols); 1903 1903 u16 *src, *dest; 1904 + bool uni_lines_stale; 1904 1905 1905 1906 if (vc->vc_saved_screen == NULL) 1906 1907 return; /* Not inside an alt-screen */ ··· 1910 1909 dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols; 1911 1910 memcpy(dest, src, 2 * cols); 1912 1911 } 1913 - vc_uniscr_set(vc, vc->vc_saved_uni_lines); 1912 + /* 1913 + * If the console was resized while in the alternate screen, 1914 + * vc_saved_uni_lines was allocated for the old dimensions. 1915 + * Restoring it would cause out-of-bounds accesses. Discard it 1916 + * and let the unicode screen be lazily rebuilt. 1917 + */ 1918 + uni_lines_stale = vc->vc_saved_rows != vc->vc_rows || 1919 + vc->vc_saved_cols != vc->vc_cols; 1920 + if (uni_lines_stale) 1921 + vc_uniscr_free(vc->vc_saved_uni_lines); 1922 + else 1923 + vc_uniscr_set(vc, vc->vc_saved_uni_lines); 1914 1924 vc->vc_saved_uni_lines = NULL; 1915 1925 restore_cur(vc); 1916 1926 /* Update the entire screen */