⬢ DragonFlyBSD Kernel Audit
DF-5537 / fix.diff
← back to finding ↓ download raw
--- a/sys/platform/vkernel64/platform/console.c
+++ b/sys/platform/vkernel64/platform/console.c
@@ -272,20 +272,29 @@
 vconswinch_intr(void *arg __unused, void *frame __unused)
 {
 	struct winsize newsize;
+	struct consdev *cp;
+	struct tty *tp;
 
-	if (vconsole != NULL && vconsole->cn_dev->si_tty != NULL) {
-		ioctl(0, TIOCGWINSZ, &newsize);
-		/*
-		 * ttioctl(vconsole->cn_dev->si_tty, TIOCSWINSZ, &newsize, 0);
-		 * I wished.  Unfortunately this needs a curproc, so do it
-		 * manually.
-		 */
-		if (bcmp(&newsize, &vconsole->cn_dev->si_tty->t_winsize,
-			 sizeof(newsize)) != 0) {
-			vconsole->cn_dev->si_tty->t_winsize = newsize;
-			pgsignal(vconsole->cn_dev->si_tty->t_pgrp, SIGWINCH, 1);
-		}
+	if ((cp = vconsole) == NULL)
+		return;
+	if ((tp = cp->cn_dev->si_tty) == NULL)
+		return;
+	/*
+	 * ttioctl(tp, TIOCSWINSZ, &newsize, 0); I wished.  Unfortunately
+	 * this needs a curproc, so do it manually -- but under the tty
+	 * token, like every other t_winsize / t_pgrp consumer (see
+	 * vconsvirt_intr below and ttioctl()'s TIOCSWINSZ handling).
+	 *
+	 * Caching cp/tp in locals also closes the double-load race of
+	 * vconsole against vconsterm().
+	 */
+	lwkt_gettoken(&tp->t_token);
+	ioctl(0, TIOCGWINSZ, &newsize);
+	if (bcmp(&newsize, &tp->t_winsize, sizeof(newsize)) != 0) {
+		tp->t_winsize = newsize;
+		pgsignal(tp->t_pgrp, SIGWINCH, 1);
 	}
+	lwkt_reltoken(&tp->t_token);
 }
 
 /*