DragonFlyBSD Kernel Audit
DF-0124 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c
--- a/sys/kern/tty_cons.c
+++ b/sys/kern/tty_cons.c
@@ -364,7 +364,12 @@
 	 *
 	 * XXX at the moment we assume that the port forwarding function
 	 * is synchronous for open.
+	 *
+	 * cn_ops is flagged D_MPSAFE but the cn_is_open / cn_phys_is_open /
+	 * openmode / openflag RMW below is unsynchronized; serialize on
+	 * tty_token (same token the rest of the console TTY path holds).
 	 */
+	lwkt_gettoken(&tty_token);
 	if (!cn_mute) {
 		ap->a_head.a_dev = physdev;
 		retval = dev_doperate_ops(cn_fwd_ops, &ap->a_head);
@@ -383,6 +388,7 @@
 		}
 		dev->si_tty = cndev->si_tty;
 	}
+	lwkt_reltoken(&tty_token);
 	return (retval);
 }
 
@@ -399,9 +405,12 @@
 	cdev_t cndev;
 	cdev_t physdev;
 	cdev_t dev = ap->a_head.a_dev;
+	int retval;
 
 	if (cn_tab == NULL || cn_fwd_ops == NULL)
 		return(0);
+
+	lwkt_gettoken(&tty_token);
 	cndev = cn_tab->cn_dev;
 	cn_tp = cndev->si_tty;
 	physdev = (dev == cn_devfsdev) ? cndev : dev;
@@ -432,9 +441,12 @@
 	}
 	if (cn_fwd_ops) {
 		ap->a_head.a_dev = dev;
-		return (dev_doperate_ops(cn_fwd_ops, &ap->a_head));
+		retval = dev_doperate_ops(cn_fwd_ops, &ap->a_head);
+	} else {
+		retval = 0;
 	}
-	return (0);
+	lwkt_reltoken(&tty_token);
+	return (retval);
 }
 
 /*