git: f958aa7e754d - main - vt: Fix timer race between vtterm_splash() and vt_flush()

From: Ahmad Khalifa <vexeduxr_at_FreeBSD.org>
Date: Fri, 02 Oct 2026 02:20:58 UTC
The branch main has been updated by vexeduxr:

URL: https://cgit.FreeBSD.org/src/commit/?id=f958aa7e754d88f3955f3c30a13f0e492822e3c3

commit f958aa7e754d88f3955f3c30a13f0e492822e3c3
Author:     Quentin Thébault <quentin.thebault@defenso.fr>
AuthorDate: 2026-09-30 01:42:33 +0000
Commit:     Ahmad Khalifa <vexeduxr@FreeBSD.org>
CommitDate: 2026-10-02 02:13:15 +0000

    vt: Fix timer race between vtterm_splash() and vt_flush()
    
    Current code leads to console text being drawn over the splash image.
    
    vt_flush() draws while holding the vtbuf lock. Have it check VDF_SPLASH
    under it too, and make vtterm_splash() take the vtbuf lock when setting
    it, before drawing the splash.
    
    Sponsored by:   Defenso
    Signed-off-by:  Quentin Thébault <quentin.thebault@defenso.fr>
    Reviewed by:    vexeduxr
    Differential Revision:  https://reviews.freebsd.org/D59928
---
 sys/dev/vt/vt_core.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 0030a3868219..0ea2ec58f4cc 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -1501,7 +1501,7 @@ vt_flush(struct vt_device *vd)
 	if (vw == NULL)
 		return (0);
 
-	if (vd->vd_flags & VDF_SPLASH || vw->vw_flags & VWF_BUSY)
+	if (vw->vw_flags & VWF_BUSY)
 		return (0);
 
 	vf = vw->vw_font;
@@ -1511,6 +1511,13 @@ vt_flush(struct vt_device *vd)
 	VT_FLUSH_LOCK(vd);
 
 	vtbuf_lock(&vw->vw_buf);
+
+	if (vd->vd_flags & VDF_SPLASH) {
+		vtbuf_unlock(&vw->vw_buf);
+		VT_FLUSH_UNLOCK(vd);
+		return (0);
+	}
+
 	inside_vt_flush = true;
 
 #ifndef SC_NO_CUTPASTE
@@ -1697,17 +1704,21 @@ vtterm_splash(struct vt_device *vd)
 
 	si = MD_FETCH(preload_kmdp, rebooting == 1 ? MODINFOMD_SHTDWNSPLASH :
 	    MODINFOMD_SPLASH, struct splash_info *);
+	/* Quit before taking the lock if the backend lacks something. */
 	if (si == NULL) {
 		if (vd->vd_driver->vd_bitblt_bmp == NULL)
 			return;
-	} else if (vd->vd_driver->vd_bitblt_argb == NULL)
+	} else if (vd->vd_driver->vd_bitblt_argb == NULL || si->si_depth != 4)
+		return;
+	if (rebooting == 1 && vd->vd_driver->vd_blank == NULL)
 		return;
 
-	if (rebooting == 1) {
-		if (vd->vd_driver->vd_blank == NULL)
-			return;
+	vtbuf_lock(&vd->vd_curwindow->vw_buf);
+	vd->vd_flags |= VDF_SPLASH;
+	vtbuf_unlock(&vd->vd_curwindow->vw_buf);
+
+	if (rebooting == 1)
 		vd->vd_driver->vd_blank(vd, TC_BLACK);
-	}
 
 	if (si == NULL) {
 		top = (vd->vd_height - vt_logo_height) / 2;
@@ -1716,8 +1727,6 @@ vtterm_splash(struct vt_device *vd)
 		    vd->vd_curwindow, vt_logo_image, NULL, vt_logo_width,
 		    vt_logo_height, left, top, TC_WHITE, TC_BLACK);
 	} else {
-		if (si->si_depth != 4)
-			return;
 		image = (uintptr_t)si + sizeof(struct splash_info);
 		image = roundup2(image, 8);
 		top = (vd->vd_height - si->si_height) / 2;
@@ -1726,7 +1735,6 @@ vtterm_splash(struct vt_device *vd)
 		    (unsigned char *)image, si->si_width, si->si_height,
 		    left, top);
 	}
-	vd->vd_flags |= VDF_SPLASH;
 }
 #endif