git: 6269b9bce0e3 - stable/14 - tty: Revalidate after dropping the tty lock in ioctl handlers

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 25 Aug 2026 16:00:03 UTC
The branch stable/14 has been updated by markj:

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

commit 6269b9bce0e344336e9cc4f35ebf3fa66d74ca10
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-08-24 18:14:18 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-08-25 15:58:57 +0000

    tty: Revalidate after dropping the tty lock in ioctl handlers
    
    The TIOCSCTTY ioctl handler drops the tty lock in order to acquire the
    proctree relock.  After relocking the tty, it did not revalidate the
    tty state, and it could end up linking a doomed tty to the calling
    process' session.  This race can be exploited to escalate privileges.
    
    TIOCSPGRP has a similar race, fix that too.
    
    Approved by:    so
    Security:       FreeBSD-SA-26:62.tty
    Security:       CVE-2026-58093
    Reported by:    tsune of GMO Cybersecurity by Ierae, Inc. working with TrendAI Zero Day Initiative
    Reviewed by:    kib
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D59126
---
 sys/kern/tty.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 3bacbde3d1b0..9578dc876ea6 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1877,7 +1877,12 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		/* XXX: This looks awful. */
 		tty_unlock(tp);
 		sx_xlock(&proctree_lock);
-		tty_lock(tp);
+		error = ttydev_enter(tp);
+		if (error != 0) {
+			sx_xunlock(&proctree_lock);
+			tty_lock(tp);
+			return (error);
+		}
 
 		if (!SESS_LEADER(p)) {
 			/* Only the session leader may do this. */
@@ -1941,7 +1946,12 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 			tty_lock(tp);
 			return (EPERM);
 		}
-		tty_lock(tp);
+		error = ttydev_enter(tp);
+		if (error != 0) {
+			sx_sunlock(&proctree_lock);
+			tty_lock(tp);
+			return (error);
+		}
 
 		/*
 		 * Determine if this TTY is the controlling TTY after