DragonFlyBSD Kernel Audit
DF-0176 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c
--- a/sys/kern/tty_tty.c
+++ b/sys/kern/tty_tty.c
@@ -233,6 +233,7 @@
 {
 	struct vnode *ttyvp;
 	struct proc *p = curproc;
+	int error;
 
 	KKASSERT(p);
 	lwkt_gettoken(&p->p_token);
@@ -261,8 +262,19 @@
 	}
 	lwkt_reltoken(&p->p_token);
 
-	return (VOP_IOCTL(ttyvp, ap->a_cmd, ap->a_data, ap->a_fflag,
-			  ap->a_cred, ap->a_sysmsg));
+	/*
+	 * Take a vnode reference so ttyvp cannot be vrele'd/reclaimed
+	 * while VOP_IOCTL runs.  Matches what cttyread/cttywrite do via
+	 * vget(); cttyioctl previously dereferenced ttyvp unlocked.
+	 * (DF-0176)
+	 */
+	error = vget(ttyvp, LK_EXCLUSIVE | LK_RETRY);
+	if (error)
+		return (EIO);
+	error = VOP_IOCTL(ttyvp, ap->a_cmd, ap->a_data, ap->a_fflag,
+			  ap->a_cred, ap->a_sysmsg);
+	vput(ttyvp);
+	return (error);
 }
 
 static struct filterops cttyfiltops_read =