DragonFlyBSD Kernel Audit
DF-2687 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/tty.c	2026-08-30 20:12:26.875972177 +0000
+++ b/sys/kern/tty.c	2026-08-30 20:13:08.707430133 +0000
@@ -1195,8 +1195,33 @@
 		otp = p->p_session->s_ttyp;
 		p->p_session->s_ttyp = tp;
 		p->p_flags |= P_CONTROLT;
-		if (otp)
+		if (otp) {
+			/*
+			 * Fully dissociate the tty we are replacing.
+			 * Otherwise otp->t_session keeps pointing at the
+			 * session while s_ttyp no longer references otp;
+			 * when the session is destroyed sess_rele() only
+			 * repairs s_ttyp's t_session, leaving otp with a
+			 * dangling t_session that is later dereferenced
+			 * by ttyclearsession() and ttymodem().
+			 */
+			if (otp != tp) {
+				struct pgrp *xpgrp;
+
+				lwkt_gettoken(&otp->t_token);
+				if (otp->t_session == p->p_session) {
+					otp->t_session = NULL;
+					xpgrp = otp->t_pgrp;
+					otp->t_pgrp = NULL;
+				} else {
+					xpgrp = NULL;
+				}
+				lwkt_reltoken(&otp->t_token);
+				if (xpgrp)
+					pgrel(xpgrp);
+			}
 			ttyunhold(otp);
+		}
 		if (opgrp) {
 			pgrel(opgrp);
 			opgrp = NULL;
--- a/sys/vfs/devfs/devfs_vnops.c	2026-08-30 20:12:26.879972126 +0000
+++ b/sys/vfs/devfs/devfs_vnops.c	2026-08-30 20:13:08.715430029 +0000
@@ -1544,6 +1544,18 @@
 		    "devfs_fo_ioctl() called! for dev %s\n",
 		    dev->si_name);
 
+	/*
+	 * A pty master must never become a controlling terminal: its
+	 * last close clears s_ttyvp (devfs_spec_close) without running
+	 * ttyclose(), which orphans the tty's t_session and allows the
+	 * session to be reassigned while the first tty still points at
+	 * it.  Reject before the device ioctl runs.
+	 */
+	if (com == TIOCSCTTY && (dev_dflags(dev) & D_MASTER)) {
+		error = EINVAL;
+		goto out;
+	}
+
 	if (com == FIODTYPE) {
 		*(int *)data = dev_dflags(dev) & D_TYPEMASK;
 		error = 0;
--- a/sys/kern/vfs_vnops.c	2026-08-30 20:12:26.879972126 +0000
+++ b/sys/kern/vfs_vnops.c	2026-08-30 20:13:08.727429874 +0000
@@ -1026,6 +1026,16 @@
 			error = 0;
 			break;
 		}
+		/*
+		 * A pty master must never become a controlling
+		 * terminal (see devfs_fo_ioctl); reject before the
+		 * device ioctl runs.
+		 */
+		if (com == TIOCSCTTY && vp->v_type == VCHR && vp->v_rdev &&
+		    (dev_dflags(vp->v_rdev) & D_MASTER)) {
+			error = EINVAL;
+			break;
+		}
 		error = VOP_IOCTL(vp, com, data, fp->f_flag, ucred, msg);
 		if (error == 0 && com == TIOCSCTTY) {
 			struct proc *p = curthread->td_proc;