git: 2469f84bec79 - stable/15 - kern/tty.c: Exterrorize returns

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 05 Sep 2026 00:35:43 UTC
The branch stable/15 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2469f84bec79b090b261a6b075c76304541e2070

commit 2469f84bec79b090b261a6b075c76304541e2070
Author:     Gleb Popov <arrowd@FreeBSD.org>
AuthorDate: 2026-08-03 19:23:11 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-09-05 00:33:46 +0000

    kern/tty.c: Exterrorize returns
    
    (cherry picked from commit 62ccaec3dba6272590d97cc0aa0df28fd3d08d1c)
---
 lib/libc/gen/exterr_cat_filenames.h |  1 +
 sys/kern/tty.c                      | 49 ++++++++++++++++++++-----------------
 sys/sys/exterr_cat.h                |  1 +
 3 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/lib/libc/gen/exterr_cat_filenames.h b/lib/libc/gen/exterr_cat_filenames.h
index d55396a1b286..b28dbdb499a4 100644
--- a/lib/libc/gen/exterr_cat_filenames.h
+++ b/lib/libc/gen/exterr_cat_filenames.h
@@ -11,6 +11,7 @@
 	[EXTERR_CAT_PROCEXIT] = "kern/kern_exit.c",
 	[EXTERR_CAT_FORK] = "kern/kern_fork.c",
 	[EXTERR_CAT_GENIO] = "kern/sys_generic.c",
+	[EXTERR_CAT_TTY] = "kern/tty.c",
 	[EXTERR_CAT_VFSBIO] = "kern/vfs_bio.c",
 	[EXTERR_CAT_INOTIFY] = "kern/vfs_inotify.c",
 	[EXTERR_CAT_VFSSYSCALL] = "kern/vfs_syscalls.c",
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 7a401695be97..b7ead9ecf417 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -66,6 +66,8 @@
 #undef TTYDEFCHARS
 #include <sys/ucred.h>
 #include <sys/vnode.h>
+#define EXTERR_CATEGORY EXTERR_CAT_TTY
+#include <sys/exterrvar.h>
 
 #include <fs/devfs/devfs.h>
 
@@ -224,7 +226,7 @@ ttydev_enter(struct tty *tp)
 	if (tty_gone(tp) || !tty_opened(tp)) {
 		/* Device is already gone. */
 		tty_unlock(tp);
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "ttydev_enter: device is gone"));
 	}
 
 	return (0);
@@ -285,7 +287,7 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused,
 	if (tty_gone(tp)) {
 		/* Device is already gone. */
 		tty_unlock(tp);
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "ttydev_open: device is gone"));
 	}
 
 	/*
@@ -491,7 +493,7 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig,
 			/* Don't allow the action to happen. */
 			PROC_UNLOCK(p);
 			PGRP_UNLOCK(pg);
-			return (EIO);
+			return (EXTERROR(EIO, "cannot wait in background"));
 		}
 		PROC_UNLOCK(p);
 
@@ -874,7 +876,7 @@ ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
 
 	tty_lock(tp);
 	if (tty_gone(tp)) {
-		error = ENODEV;
+		error = (EXTERROR(ENODEV, "ttyil_ioctl: device is gone"));
 		goto done;
 	}
 
@@ -1260,23 +1262,23 @@ tty_drop_ctty(struct tty *tp, struct proc *p)
 	tty_lock(tp);
 	if (tty_gone(tp)) {
 		sx_xunlock(&proctree_lock);
-		return (ENODEV);
+		return (EXTERROR(ENODEV, "tty_drop_ctty: device is gone"));
 	}
 
 	/*
 	 * If the session doesn't have a controlling TTY, or if we weren't
-	 * invoked on the controlling TTY, we'll return ENOIOCTL as we've
+	 * invoked on the controlling TTY, we'll return ENOTTY as we've
 	 * historically done.
 	 */
 	session = p->p_session;
 	if (session->s_ttyp == NULL || session->s_ttyp != tp) {
 		sx_xunlock(&proctree_lock);
-		return (ENOTTY);
+		return (EXTERROR(ENOTTY, "no controlling tty"));
 	}
 
 	if (!SESS_LEADER(p)) {
 		sx_xunlock(&proctree_lock);
-		return (EPERM);
+		return (EXTERROR(EPERM, "not a session leader"));
 	}
 
 	PROC_LOCK(p);
@@ -1607,7 +1609,7 @@ tty_wait(struct tty *tp, struct cv *cv)
 
 	/* Bail out when the device slipped away. */
 	if (tty_gone(tp))
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "tty_wait: device is gone"));
 
 	/* Restart the system call when we may have been revoked. */
 	if (tp->t_revokecnt != revokecnt)
@@ -1666,7 +1668,7 @@ tty_timedwait(struct tty *tp, struct cv *cv, int hz)
 
 	/* Bail out when the device slipped away. */
 	if (tty_gone(tp))
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "tty_timedwait: device is gone"));
 
 	/* Restart the system call when we may have been revoked. */
 	if (tp->t_revokecnt != revokecnt)
@@ -1714,7 +1716,7 @@ tty_sti_check(struct tty *tp, int fflag, struct thread *td)
 {
 	/* Check for global disable. */
 	if (!tty_tiocsti)
-		return (EPERM);
+		return (EXTERROR(EPERM, "security.bsd.allow_tiocsti"));
 
 	/* Root can bypass all of our constraints. */
 	if (priv_check(td, PRIV_TTY_STI) == 0)
@@ -1722,11 +1724,11 @@ tty_sti_check(struct tty *tp, int fflag, struct thread *td)
 
 	/* Unprivileged users must have it opened for read. */
 	if ((fflag & FREAD) == 0)
-		return (EPERM);
+		return (EXTERROR(EPERM, "opened read-only"));
 
 	/* It must also be their controlling tty. */
 	if (!tty_is_ctty(tp, td->td_proc))
-		return (EACCES);
+		return (EXTERROR(EACCES, "not a controlling tty"));
 
 	return (0);
 }
@@ -1913,7 +1915,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		return (0);
 	case TIOCGPGRP:
 		if (!tty_is_ctty(tp, td->td_proc))
-			return (ENOTTY);
+			return (EXTERROR(ENOTTY, "not a controlling tty"));
 
 		if (tp->t_pgrp != NULL)
 			*(int *)data = tp->t_pgrp->pg_id;
@@ -1922,7 +1924,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		return (0);
 	case TIOCGSID:
 		if (!tty_is_ctty(tp, td->td_proc))
-			return (ENOTTY);
+			return (EXTERROR(ENOTTY, "not a controlling tty"));
 
 		MPASS(tp->t_session);
 		*(int *)data = tp->t_session->s_sid;
@@ -1945,7 +1947,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		if (!SESS_LEADER(p)) {
 			/* Only the session leader may do this. */
 			sx_xunlock(&proctree_lock);
-			return (EPERM);
+			return (EXTERROR(EPERM, "not a session leader"));
 		}
 
 		if (tp->t_session != NULL && tp->t_session == p->p_session) {
@@ -1969,7 +1971,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 			 * killed or the TTY revoked.
 			 */
 			sx_xunlock(&proctree_lock);
-			return (EPERM);
+			return (EXTERROR(EPERM, "session already has CTTY"));
 		}
 
 		/* Connect the session to the TTY. */
@@ -2002,7 +2004,10 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
 			sx_sunlock(&proctree_lock);
 			tty_lock(tp);
-			return (EPERM);
+			return (EXTERROR(EPERM,
+			    "pgrp %jd belongs to other session %jd",
+			    pg != NULL ? pg->pg_id : -1,
+			    td->td_proc->p_session->s_sid));
 		}
 		error = ttydev_enter(tp);
 		if (error != 0) {
@@ -2017,7 +2022,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
 		 */
 		if (!tty_is_ctty(tp, td->td_proc)) {
 			sx_sunlock(&proctree_lock);
-			return (ENOTTY);
+			return (EXTERROR(ENOTTY, "not a controlling tty"));
 		}
 		tp->t_pgrp = pg;
 		sx_sunlock(&proctree_lock);
@@ -2109,7 +2114,7 @@ tty_ioctl(struct tty *tp, u_long cmd, void *data, int fflag, struct thread *td)
 	tty_assert_locked(tp);
 
 	if (tty_gone(tp))
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "tty_ioctl: device is gone"));
 
 	error = ttydevsw_ioctl(tp, cmd, data, td);
 	if (error == ENOIOCTL)
@@ -2307,7 +2312,7 @@ ttyconsdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 
 	/* System has no console device. */
 	if (dev_console_filename == NULL)
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "system has no console device"));
 
 	/* Look up corresponding TTY by device name. */
 	sx_slock(&tty_list_sx);
@@ -2321,7 +2326,7 @@ ttyconsdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 
 	/* System console has no TTY associated. */
 	if (dev_console->si_drv1 == NULL)
-		return (ENXIO);
+		return (EXTERROR(ENXIO, "system console has no TTY attached"));
 
 	return (ttydev_open(dev, oflags, devtype, td));
 }
diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h
index 015eb6a1ae76..78d52bfa6ced 100644
--- a/sys/sys/exterr_cat.h
+++ b/sys/sys/exterr_cat.h
@@ -39,6 +39,7 @@
 #define	EXTERR_CAT_FUSE_DEVICE	14
 #define	EXTERR_CAT_FORK		15
 #define	EXTERR_CAT_PROCEXIT	16
+#define	EXTERR_CAT_TTY		22
 
 #endif