From b6734bf8f2673f2586822c2d999306b09f29c2d6 Mon Sep 17 00:00:00 2001 From: Martin Pieuchot Date: Fri, 8 May 2020 07:31:47 +0000 Subject: Do not wait indefinitely for flushing when closing a tty. This prevent exiting processes from hanging when a slave pseudo terminal is close(2)d before its master. From NetBSD via anton@. Reported-by: syzbot+2ed25b5c40d11e4c3beb@syzkaller.appspotmail.com ok anton@, kettenis@ --- sys/kern/tty.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 431b22653de..e9f98f87e01 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.154 2020/04/07 13:27:51 visa Exp $ */ +/* $OpenBSD: tty.c,v 1.155 2020/05/08 07:31:46 mpi Exp $ */ /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */ /*- @@ -80,6 +80,8 @@ void filt_ttyrdetach(struct knote *kn); int filt_ttywrite(struct knote *kn, long hint); void filt_ttywdetach(struct knote *kn); void ttystats_init(struct itty **, size_t *); +int ttywait_nsec(struct tty *, uint64_t); +int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t); /* Symbolic sleep message strings. */ char ttclos[] = "ttycls"; @@ -1202,10 +1204,10 @@ ttnread(struct tty *tp) } /* - * Wait for output to drain. + * Wait for output to drain, or if this times out, flush it. */ int -ttywait(struct tty *tp) +ttywait_nsec(struct tty *tp, uint64_t nsecs) { int error, s; @@ -1219,7 +1221,10 @@ ttywait(struct tty *tp) (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) && tp->t_oproc) { SET(tp->t_state, TS_ASLEEP); - error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout); + error = ttysleep_nsec(tp, &tp->t_outq, TTOPRI | PCATCH, + ttyout, nsecs); + if (error == EWOULDBLOCK) + ttyflush(tp, FWRITE); if (error) break; } else @@ -1229,6 +1234,12 @@ ttywait(struct tty *tp) return (error); } +int +ttywait(struct tty *tp) +{ + return (ttywait_nsec(tp, INFSLP)); +} + /* * Flush if successfully wait. */ @@ -1237,7 +1248,8 @@ ttywflush(struct tty *tp) { int error; - if ((error = ttywait(tp)) == 0) + error = ttywait_nsec(tp, SEC_TO_NSEC(5)); + if (error == 0 || error == EWOULDBLOCK) ttyflush(tp, FREAD); return (error); } @@ -2280,12 +2292,18 @@ tputchar(int c, struct tty *tp) */ int ttysleep(struct tty *tp, void *chan, int pri, char *wmesg) +{ + return (ttysleep_nsec(tp, chan, pri, wmesg, INFSLP)); +} + +int +ttysleep_nsec(struct tty *tp, void *chan, int pri, char *wmesg, uint64_t nsecs) { int error; short gen; gen = tp->t_gen; - if ((error = tsleep_nsec(chan, pri, wmesg, INFSLP)) != 0) + if ((error = tsleep_nsec(chan, pri, wmesg, nsecs)) != 0) return (error); return (tp->t_gen == gen ? 0 : ERESTART); } -- cgit v1.2.3