The branch stable/14 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=012c194f39e872aad9e7a9798ef94662832bd11d

commit 012c194f39e872aad9e7a9798ef94662832bd11d
Author:     Robert Wing <r...@freebsd.org>
AuthorDate: 2023-12-19 00:40:46 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2024-10-10 20:28:20 +0000

    tty: delete knotes when TTY is revoked
    
    Do not clear knotes from the TTY until it gets dealloc'ed, unless the
    TTY is being revoked, in that case delete the knotes when closed is
    called on the TTY.
    
    When knotes are cleared from a knlist, those knotes become detached from
    the knlist. And when an event is triggered on a detached knote there
    isn't an associated knlist and therefore no lock will be taken when the
    event is triggered.
    
    This becomes a problem when a detached knote is triggered on a TTY since
    the mutex for a TTY is also used as the lock for its knlists. This
    scenario ends up calling the TTY event handlers without the TTY lock
    being held and tripping on asserts in the event handlers.
    
    PR:             272151
    Reviewed by:    kib, markj
    Differential Revision:  https://reviews.freebsd.org/D41605
    
    (cherry picked from commit acd5638e268a6706f6b7ad84947a8425e8d51ef7)
---
 sys/kern/tty.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 6848fbf558b0..b6e300321e9c 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -254,9 +254,6 @@ ttydev_leave(struct tty *tp)
        ttyoutq_free(&tp->t_outq);
        tp->t_outlow = 0;
 
-       knlist_clear(&tp->t_inpoll.si_note, 1);
-       knlist_clear(&tp->t_outpoll.si_note, 1);
-
        if (!tty_gone(tp))
                ttydevsw_close(tp);
 
@@ -370,7 +367,7 @@ done:       tp->t_flags &= ~TF_OPENCLOSE;
 
 static int
 ttydev_close(struct cdev *dev, int fflag, int devtype __unused,
-    struct thread *td __unused)
+    struct thread *td)
 {
        struct tty *tp = dev->si_drv1;
 
@@ -393,8 +390,11 @@ ttydev_close(struct cdev *dev, int fflag, int devtype 
__unused,
        }
 
        /* If revoking, flush output now to avoid draining it later. */
-       if (fflag & FREVOKE)
+       if ((fflag & FREVOKE) != 0) {
                tty_flush(tp, FWRITE);
+               knlist_delete(&tp->t_inpoll.si_note, td, 1);
+               knlist_delete(&tp->t_outpoll.si_note, td, 1);
+       }
 
        tp->t_flags &= ~TF_EXCLUDE;
 
@@ -1121,6 +1121,8 @@ tty_dealloc(void *arg)
        ttyoutq_free(&tp->t_outq);
        seldrain(&tp->t_inpoll);
        seldrain(&tp->t_outpoll);
+       knlist_clear(&tp->t_inpoll.si_note, 0);
+       knlist_clear(&tp->t_outpoll.si_note, 0);
        knlist_destroy(&tp->t_inpoll.si_note);
        knlist_destroy(&tp->t_outpoll.si_note);
 

Reply via email to