| From 3ddbea7542ae529c1a88ef9a8b1ce169126211f6 Mon Sep 17 00:00:00 2001 |
| From: Nicolas Pitre <nico@fluxnic.net> |
| Date: Fri, 27 Mar 2026 23:09:47 -0400 |
| Subject: vt: resize saved unicode buffer on alt screen exit after resize |
| |
| From: Nicolas Pitre <nico@fluxnic.net> |
| |
| commit 3ddbea7542ae529c1a88ef9a8b1ce169126211f6 upstream. |
| |
| Instead of discarding the saved unicode buffer when the console was |
| resized while in the alternate screen, resize it to the current |
| dimensions using vc_uniscr_copy_area() to preserve its content. This |
| properly restores the unicode screen on alt screen exit rather than |
| lazily rebuilding it from a lossy reverse glyph translation. |
| |
| On allocation failure the stale buffer is freed and vc_uni_lines is |
| set to NULL so it gets lazily rebuilt via vc_uniscr_check() when next |
| needed. |
| |
| Fixes: 40014493cece ("vt: discard stale unicode buffer on alt screen exit after resize") |
| Cc: stable <stable@kernel.org> |
| Signed-off-by: Nicolas Pitre <nico@fluxnic.net> |
| Link: https://patch.msgid.link/3nsr334n-079q-125n-7807-n4nq818758ns@syhkavp.arg |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/tty/vt/vt.c | 24 +++++++++++++++--------- |
| 1 file changed, 15 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/tty/vt/vt.c |
| +++ b/drivers/tty/vt/vt.c |
| @@ -1907,7 +1907,6 @@ static void leave_alt_screen(struct vc_d |
| unsigned int rows = min(vc->vc_saved_rows, vc->vc_rows); |
| unsigned int cols = min(vc->vc_saved_cols, vc->vc_cols); |
| u16 *src, *dest; |
| - bool uni_lines_stale; |
| |
| if (vc->vc_saved_screen == NULL) |
| return; /* Not inside an alt-screen */ |
| @@ -1918,16 +1917,23 @@ static void leave_alt_screen(struct vc_d |
| } |
| /* |
| * If the console was resized while in the alternate screen, |
| - * vc_saved_uni_lines was allocated for the old dimensions. |
| - * Restoring it would cause out-of-bounds accesses. Discard it |
| - * and let the unicode screen be lazily rebuilt. |
| + * resize the saved unicode buffer to the current dimensions. |
| + * On allocation failure new_uniscr is NULL, causing the old |
| + * buffer to be freed and vc_uni_lines to be lazily rebuilt |
| + * via vc_uniscr_check() when next needed. |
| */ |
| - uni_lines_stale = vc->vc_saved_rows != vc->vc_rows || |
| - vc->vc_saved_cols != vc->vc_cols; |
| - if (uni_lines_stale) |
| + if (vc->vc_saved_uni_lines && |
| + (vc->vc_saved_rows != vc->vc_rows || |
| + vc->vc_saved_cols != vc->vc_cols)) { |
| + u32 **new_uniscr = vc_uniscr_alloc(vc->vc_cols, vc->vc_rows); |
| + |
| + if (new_uniscr) |
| + vc_uniscr_copy_area(new_uniscr, vc->vc_cols, vc->vc_rows, |
| + vc->vc_saved_uni_lines, cols, 0, rows); |
| vc_uniscr_free(vc->vc_saved_uni_lines); |
| - else |
| - vc_uniscr_set(vc, vc->vc_saved_uni_lines); |
| + vc->vc_saved_uni_lines = new_uniscr; |
| + } |
| + vc_uniscr_set(vc, vc->vc_saved_uni_lines); |
| vc->vc_saved_uni_lines = NULL; |
| restore_cur(vc); |
| /* Update the entire screen */ |