From nobody Thu Apr 2 15:41:48 2026 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 564FE31618C for ; Fri, 27 Mar 2026 16:56:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630592; cv=none; b=aCJFE11F9R8JYHhG5auAoKC9egmjlSeWe7po3uELUhrhuRWrbuda5GvgssGLcdkJwGeJYZ0J929RnKjyjZ7sQF4Q6lfbrIa3j6Pw8lRiW7rUd6vjbKuqHQks0SIQkPcTMQlZxGXxbXb/Q/lpFMTUjjQgSF6Zb6wPPvoFhtnQrFI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630592; c=relaxed/simple; bh=mW82cped2hCiw5sDJqn+wjxsIZQeXzzzX4YwQALG0Wc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M7Yrv2+7z7iC+L56YVUxV+z6t/Gx3BcmM/0HrDvDZxhxzcjojdyowe4D2OqkvYP3c4Gf8nGOw3c1X4aaTNoB3YqpxXYt+0FiE6advf3nM1H6/OyEgfSIi/CA9CRMRHIaDl30Fg9J5lMtJTLvTQ+hvEe1yjMuA/W0PfQhuGUAbEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lO/YDPnk; arc=none smtp.client-ip=209.85.128.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lO/YDPnk" Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-486fd3a577eso21064415e9.1 for ; Fri, 27 Mar 2026 09:56:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774630590; x=1775235390; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wsJ2oBBJ557jnH70rKnLDSkb5/BQjqsRz3QFg17o8Uk=; b=lO/YDPnk50RG54B1rqITcmZBB+OEx/AS9CfT6JdmYz2tuz6BUIy1jmB2wp6nIClsmQ Mh9R2MqS8zgv3ZV8WZfRyPObzLtjiAdQC2mITFzmj0TFbFxhBPOKCMJEhxFqa/m4JbPQ dpWl1KgYWt+IJ4NJBCiIt2puKauptx5QlCO3t4CWPBZYkmL2thXjkaHp0yHWkUqXUGg/ 41ztQQeOM/BJX0sTcAcYrxEWMg2tqYFIbVMm6p+c9lHGwtC/w1TfMjWngpJ55LMixTos a0hTaaToOk528SNsqWkpP4Qgk+tSLGhIPHq/3uHf1MsGIeqVLkWZTennFkGec9RYtRqG G/Ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774630590; x=1775235390; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wsJ2oBBJ557jnH70rKnLDSkb5/BQjqsRz3QFg17o8Uk=; b=kHEMk5vl5piDwGW93NMJKA9YabccBWJYHOQhDFkF0XmosUMvK/4s8TEk+a2e8kmhfD NjTaJxwh2PSuNByRpSZKf8u0A9LbFQllg9zu6Iq2+0utq8WpAIG5Jad8jTKNAzEMzdQl v3CLiEiE0tgIQVAo1+C3VrMBCDkW4ZDGmC2Z/C/RKddQcB05rPjF6bS/D0aI954Ndnis GX2lB0P4drGZOVQ4hD0A8XWx2rEQLXjcRxYEIeWYlH681y46CdrgSkozDRdAgvEiaooJ 5yxoqeCgSdpasw5d9T4Kk2aUWmLT3t6a8BKcNJGcNVIQdrWmQOsINfdiK4rnLxpae8FI I0fg== X-Forwarded-Encrypted: i=1; AJvYcCVNkwJLjZzoiHche/1BzCZUxsznM3Oc9T8aZPBwh0uO5VD9NexCO9PFeGjSOSeNZyXhvvUrbUHNjqkvpT0=@vger.kernel.org X-Gm-Message-State: AOJu0YwZNXXyy5ZAzDBgFCXQDlPu7YG68TZv3gHPM472Pt8gf+8mr1Ov jjta02Y1w0oK2r2YjU/jqLDpFB7rw5cRxyWWrxny4sq/gNbfbiajv7U/ X-Gm-Gg: ATEYQzwAdZHnSzwoEy/EUoySkqMToAzPVtDajeW2SGxCW/kn79igvlheoKJZVQGlUBl eyHhyYFSG5+DvuC4He7/AVIKFhlybpYxyhkLu8Tpw8vhTnDVlfWOLQy31i07CTDlYBz1YQ3Tg7e iKGuCVc9Yxb42dlnUQk96/jf68Y88ke6PkI7fCTN7S3bOp3Y/MNv5biqtvt/R2AACj1acmfi2dd qtuSfk3mVk9Uwk1BS5JjMqIxZpeCDWqNoQP52inxZPqd9TOLeQkWtoknfLgu35ax7KB+23Gmb2e Q0PeqMdD5sMnV7xjCKTACf+EDvLK7gNMuZBui5hQghIb05GaskjHHrzlVGwWYhWwedSpjsbaV1L AFTgBZ8wU3/byuyLoncQLyK2Pq1ng7wdbqanQsoL1vP61nAOtvE4LWI3jSEU8mEjP0uZybn6kes wUZTJieOelJOV8kULm0Q== X-Received: by 2002:a05:600c:c493:b0:486:ffa3:594 with SMTP id 5b1f17b1804b1-48727ef0b7dmr54779745e9.23.1774630589574; Fri, 27 Mar 2026 09:56:29 -0700 (PDT) Received: from tux ([2a00:a041:e07d:7c00:1ac0:4dff:feb8:fd3]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48722c845b8sm95410675e9.4.2026.03.27.09.56.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Mar 2026 09:56:28 -0700 (PDT) From: Liav Mordouch To: stable@vger.kernel.org Cc: gregkh@linuxfoundation.org, npitre@baylibre.com, linux-kernel@vger.kernel.org Subject: [PATCH] vt: discard stale unicode buffer on alt screen exit after resize Date: Fri, 27 Mar 2026 19:55:18 +0300 Message-ID: <20260327165519.15969-1-liavmordouch@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260327160050.31631-1-liavmordouch@gmail.com> References: <20260327160050.31631-1-liavmordouch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hi, Following up on the bug report I sent earlier. I've done some further diggi= ng and found the root cause, and I'm including a patch that fixes it. I've tes= ted it and confirmed it resolves the crash on my system. Root cause analysis: The crash I reported in csi_J is caused by a size mismatch between vc_uni_lines and the actual console dimensions. Here's what happens: 1. Console starts at 80x25. vc_uni_lines is allocated for 80x25 (25 pointers + 25*80 u32s, contiguous). 2. Something enters the alternate screen (\033[?1049h). enter_alt_screen() saves vc_uni_lines (80x25) into vc_saved_uni_lines and sets vc_uni_lines =3D NULL. 3. Console gets resized to 240x67 (amdgpu fbcon takes over). vc_do_resize= () checks "if (vc->vc_uni_lines)" -- it's NULL, so it skips reallocation. But vc_saved_uni_lines (still 80x25) is never touched by the resize. 4. Something leaves the alternate screen (\033[?1049l). leave_alt_screen() calls vc_uniscr_set(vc, vc->vc_saved_uni_lines), blindly restoring the stale 80x25 buffer. Now vc_uni_lines points to an 80x25 allocation but vc_rows=3D67, vc_cols=3D240. 5. Next clear screen (csi_J CSI_J_VISIBLE) calls vc_uniscr_clear_lines(vc, 0, 67), which iterates 67 rows with memset32(..., 240). For rows 0-24, each row only has space for 80 u32s so memset32 overflows into adjacent rows. At row 25, vc_uni_lines[25] reads from the data area (past the 25-entry pointer array), getting 0x0000002000000020 (two u32 space values read as a pointer) -- page fault, crash. This is confirmed by the registers from the oops: RDI =3D 0x0000002000000020 (bogus pointer =3D two space chars) RCX =3D 0xf0 =3D 240 (vc_cols, count for memset32) RSI =3D 0xc8 =3D 200 =3D 25*8 (byte offset =3D row index 25) RDX =3D 0x218 =3D 536 =3D 67*8 (loop end =3D 67 rows) RAX =3D 0x20 (space character, fill value) The same faulting address (0x0000002000000020) showed up across 3 separate crash boots, which makes sense since the memory layout is deterministic. The fix: in leave_alt_screen(), check if the console dimensions changed whi= le in the alternate screen. If they did, discard the stale vc_saved_uni_lines instead of restoring it. The unicode screen will be lazily rebuilt via vc_uniscr_check() when next needed. This is consistent with how the regular screen buffer restore in the same function already handles dimension mismatches using min(saved_rows, current_rows). I added a comment in the patch explaining the non-obvious reason for the conditional -- without it, a future reader would have no context for why vc_saved_uni_lines isn't unconditionally restored, and might "simplify" the code back into the buggy version. Tested on my system (Gentoo, 6.19.10, AMD Ryzen 5 5600X, RX 7800 XT with amdgpu). Previously crashed 4 out of 5 boots, now boots cleanly with the patch applied. Note: writing of this email was assisted by AI for grammar and flow. Sorry = in advance if anything reads off. --- drivers/tty/vt/vt.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1907,6 +1907,7 @@ unsigned int rows =3D min(vc->vc_saved_rows, vc->vc_rows); unsigned int cols =3D min(vc->vc_saved_cols, vc->vc_cols); u16 *src, *dest; + bool uni_lines_stale; =20 if (vc->vc_saved_screen =3D=3D NULL) return; /* Not inside an alt-screen */ @@ -1915,7 +1916,18 @@ dest =3D ((u16 *)vc->vc_origin) + r * vc->vc_cols; memcpy(dest, src, 2 * cols); } - vc_uniscr_set(vc, vc->vc_saved_uni_lines); + /* + * 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. + */ + uni_lines_stale =3D vc->vc_saved_rows !=3D vc->vc_rows || + vc->vc_saved_cols !=3D vc->vc_cols; + if (uni_lines_stale) + vc_uniscr_free(vc->vc_saved_uni_lines); + else + vc_uniscr_set(vc, vc->vc_saved_uni_lines); vc->vc_saved_uni_lines =3D NULL; restore_cur(vc); /* Update the entire screen */