git: 2520c8bd2c42 - stable/15 - tty: do not recurse on ttydev_close()

Konstantin Belousov <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.devel.stable.scm
Message-ID <[email protected]>
The branch stable/15 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2520c8bd2c42f4333bc1f4b94a78efa625bc97c9

commit 2520c8bd2c42f4333bc1f4b94a78efa625bc97c9
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-08-07 19:48:31 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-08-16 02:41:17 +0000

    tty: do not recurse on ttydev_close()
    
    (cherry picked from commit e2cfbd498af88a211b0b347861cfd989e57cd1fb)
---
 sys/kern/tty.c | 30 +++++++++++++++++++++---------
 sys/sys/tty.h  |  1 +
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 5f6afa49b70d..09ed1c6d0c5d 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -71,7 +71,7 @@
 
 static MALLOC_DEFINE(M_TTY, "tty", "tty device");
 
-static void tty_rel_free(struct tty *tp);
+static void tty_rel_free(struct tty *tp, bool inttydevclose);
 
 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
 static struct sx tty_list_sx;
@@ -229,13 +229,15 @@ ttydev_enter(struct tty *tp)
 }
 
 static void
-ttydev_leave(struct tty *tp)
+ttydev_leave(struct tty *tp, bool inttydevclose)
 {
 
 	tty_assert_locked(tp);
 
 	if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
 		/* Device is still opened somewhere. */
+		if (inttydevclose)
+			tp->t_flags &= ~TF_INDEVCLOSE;
 		tty_unlock(tp);
 		return;
 	}
@@ -262,7 +264,7 @@ ttydev_leave(struct tty *tp)
 
 	tp->t_flags &= ~TF_OPENCLOSE;
 	cv_broadcast(&tp->t_dcdwait);
-	tty_rel_free(tp);
+	tty_rel_free(tp, inttydevclose);
 }
 
 /*
@@ -363,7 +365,7 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused,
 
 done:	tp->t_flags &= ~TF_OPENCLOSE;
 	cv_broadcast(&tp->t_dcdwait);
-	ttydev_leave(tp);
+	ttydev_leave(tp, false);
 
 	return (error);
 }
@@ -375,6 +377,11 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused,
 	struct tty *tp = dev->si_drv1;
 
 	tty_lock(tp);
+	if ((tp->t_flags & TF_INDEVCLOSE) != 0) {
+		tty_unlock(tp);
+		return (0);
+	}
+	tp->t_flags |= TF_INDEVCLOSE;
 
 	/*
 	 * Don't actually close the device if it is being used as the
@@ -388,6 +395,7 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused,
 		tp->t_flags &= ~(TF_OPENED_IN|TF_OPENED_OUT);
 
 	if (tp->t_flags & TF_OPENED) {
+		tp->t_flags &= ~TF_INDEVCLOSE;
 		tty_unlock(tp);
 		return (0);
 	}
@@ -407,7 +415,7 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused,
 	cv_broadcast(&tp->t_bgwait);
 	cv_broadcast(&tp->t_dcdwait);
 
-	ttydev_leave(tp);
+	ttydev_leave(tp, true);
 
 	return (0);
 }
@@ -1144,7 +1152,7 @@ tty_dealloc(void *arg)
 }
 
 static void
-tty_rel_free(struct tty *tp)
+tty_rel_free(struct tty *tp, bool inttydevclose)
 {
 	struct cdev *dev;
 
@@ -1153,6 +1161,8 @@ tty_rel_free(struct tty *tp)
 #define	TF_ACTIVITY	(TF_GONE|TF_OPENED|TF_HOOK|TF_OPENCLOSE)
 	if (tp->t_sessioncnt != 0 || (tp->t_flags & TF_ACTIVITY) != TF_GONE) {
 		/* TTY is still in use. */
+		if (inttydevclose)
+			tp->t_flags &= ~TF_INDEVCLOSE;
 		tty_unlock(tp);
 		return;
 	}
@@ -1163,6 +1173,8 @@ tty_rel_free(struct tty *tp)
 	/* TTY can be deallocated. */
 	dev = tp->t_dev;
 	tp->t_dev = NULL;
+	if (inttydevclose)
+		tp->t_flags &= ~TF_INDEVCLOSE;
 	tty_unlock(tp);
 
 	if (dev != NULL) {
@@ -1199,7 +1211,7 @@ tty_rel_sess(struct tty *tp, struct session *sess)
 		MPASS(tp->t_pgrp == NULL);
 	}
 	tp->t_sessioncnt--;
-	tty_rel_free(tp);
+	tty_rel_free(tp, false);
 }
 
 void
@@ -1218,7 +1230,7 @@ tty_rel_gone(struct tty *tp)
 	cv_broadcast(&tp->t_dcdwait);
 
 	tp->t_flags |= TF_GONE;
-	tty_rel_free(tp);
+	tty_rel_free(tp, false);
 }
 
 static int
@@ -2226,7 +2238,7 @@ ttyhook_unregister(struct tty *tp)
 	ttydisc_optimize(tp);
 
 	/* Maybe deallocate the TTY as well. */
-	tty_rel_free(tp);
+	tty_rel_free(tp, false);
 }
 
 /*
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index f1b2646c942d..6a58908d97a4 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -87,6 +87,7 @@ struct tty {
 #define	TF_BUSY_IN	0x20000	/* Process busy in read() -- not supported. */
 #define	TF_BUSY_OUT	0x40000	/* Process busy in write(). */
 #define	TF_BUSY		(TF_BUSY_IN|TF_BUSY_OUT)
+#define	TF_INDEVCLOSE	0x80000	/* In ttydev_close() */
 	unsigned int	t_revokecnt;	/* (t) revoke() count. */
 
 	/* Buffering mechanisms. */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.