git: 59fc4cda1bfa - main - kern: tty: refactor TIOCSTI privilege checks slightly

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Wed, 28 May 2025 01:19:27 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=59fc4cda1bfa712c46d407d1e83bdd5c63e6e0e3

commit 59fc4cda1bfa712c46d407d1e83bdd5c63e6e0e3
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-05-28 01:19:17 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-05-28 01:19:17 +0000

    kern: tty: refactor TIOCSTI privilege checks slightly
    
    This removes some repetition from it and makes the flow a little more
    obvious.  Future work may find some way to add more constraints to the
    unprivileged path, add a security sysctl to disable it, or perhaps
    some combination of the two.
    
    Reviewed by:    kib, markj
    Differential Revision:  https://reviews.freebsd.org/D50506
---
 sys/kern/tty.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index b1b3b268d0e9..47f9f25cec37 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1643,6 +1643,24 @@ tty_set_winsize(struct tty *tp, const struct winsize *wsz)
 	tty_signal_pgrp(tp, SIGWINCH);
 }
 
+static int
+tty_sti_check(struct tty *tp, int fflag, struct thread *td)
+{
+	/* Root can bypass all of our constraints. */
+	if (priv_check(td, PRIV_TTY_STI) == 0)
+		return (0);
+
+	/* Unprivileged users must have it opened for read. */
+	if ((fflag & FREAD) == 0)
+		return (EPERM);
+
+	/* It must also be their controlling tty. */
+	if (!tty_is_ctty(tp, td->td_proc))
+		return (EACCES);
+
+	return (0);
+}
+
 static int
 tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
     struct thread *td)
@@ -1988,11 +2006,9 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		tty_info(tp);
 		return (0);
 	case TIOCSTI:
-		if ((fflag & FREAD) == 0 && priv_check(td, PRIV_TTY_STI))
-			return (EPERM);
-		if (!tty_is_ctty(tp, td->td_proc) &&
-		    priv_check(td, PRIV_TTY_STI))
-			return (EACCES);
+		error = tty_sti_check(tp, fflag, td);
+		if (error != 0)
+			return (error);
 		ttydisc_rint(tp, *(char *)data, 0);
 		ttydisc_rint_done(tp);
 		return (0);