untrusted comment: verify with openbsd-67-base.pub RWRmkIA877Io3i9arEaPtFFw/2ghl63HglE5WpUfoUADDlYRr4CumYpqqkFbh+qCGX2iNl0yeSRyqbXkUabVkHPYsmR54c+RXwQ= OpenBSD 6.7 errata 012, July 16, 2020: tty subsystem abuse can impact performance badly. Apply by doing: signify -Vep /etc/signify/openbsd-67-base.pub -x 012_tty.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/sys/tty.h =================================================================== RCS file: /cvs/src/sys/sys/tty.h,v diff -u -p -u -r1.38 tty.h --- sys/sys/tty.h 19 Jul 2019 00:17:16 -0000 1.38 +++ sys/sys/tty.h 14 Jul 2020 14:35:42 -0000 @@ -290,8 +290,8 @@ int ttymodem(struct tty *tp, int flag); int ttyopen(dev_t device, struct tty *tp, struct proc *p); int ttyoutput(int c, struct tty *tp); void ttypend(struct tty *tp); -void ttyretype(struct tty *tp); -void ttyrub(int c, struct tty *tp); +int ttyretype(struct tty *tp); +int ttyrub(int c, struct tty *tp); int ttysleep(struct tty *tp, void *chan, int pri, char *wmesg); int ttywait(struct tty *tp); int ttywflush(struct tty *tp); Index: sys/kern/tty.c =================================================================== RCS file: /cvs/src/sys/kern/tty.c,v diff -u -p -u -r1.154 tty.c --- sys/kern/tty.c 7 Apr 2020 13:27:51 -0000 1.154 +++ sys/kern/tty.c 14 Jul 2020 14:35:42 -0000 @@ -226,14 +226,15 @@ ttyclose(struct tty *tp) /* - * Process input of a single character received on a tty. + * Process input of a single character received on a tty. Returns 0 for + * simple operations, 1 for costly ones (ptcwrite needs to know). */ int ttyinput(int c, struct tty *tp) { int iflag, lflag; u_char *cc; - int i, error; + int i, error, ret = 0; int s; enqueue_randomness(tp->t_dev << 8 | c); @@ -341,7 +342,7 @@ parmrk: (void)putc(0377 | TTY_QUOTE, ttyflush(tp, FWRITE); ttyecho(c, tp); if (tp->t_rawq.c_cc + tp->t_canq.c_cc) - ttyretype(tp); + ret = ttyretype(tp); SET(tp->t_lflag, FLUSHO); } goto startoutput; @@ -442,7 +443,7 @@ parmrk: (void)putc(0377 | TTY_QUOTE, */ if (CCEQ(cc[VERASE], c)) { if (tp->t_rawq.c_cc) - ttyrub(unputc(&tp->t_rawq), tp); + ret = ttyrub(unputc(&tp->t_rawq), tp); goto endcase; } /* @@ -451,10 +452,11 @@ parmrk: (void)putc(0377 | TTY_QUOTE, if (CCEQ(cc[VKILL], c)) { if (ISSET(lflag, ECHOKE) && tp->t_rawq.c_cc == tp->t_rocount && - !ISSET(lflag, ECHOPRT)) + !ISSET(lflag, ECHOPRT)) { while (tp->t_rawq.c_cc) - ttyrub(unputc(&tp->t_rawq), tp); - else { + if (ttyrub(unputc(&tp->t_rawq), tp)) + ret = 1; + } else { ttyecho(c, tp); if (ISSET(lflag, ECHOK) || ISSET(lflag, ECHOKE)) @@ -476,14 +478,16 @@ parmrk: (void)putc(0377 | TTY_QUOTE, * erase whitespace */ while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') - ttyrub(c, tp); + if (ttyrub(c, tp)) + ret = 1; if (c == -1) goto endcase; /* * erase last char of word and remember the * next chars type (for ALTWERASE) */ - ttyrub(c, tp); + if (ttyrub(c, tp)) + ret = 1; c = unputc(&tp->t_rawq); if (c == -1) goto endcase; @@ -496,7 +500,8 @@ parmrk: (void)putc(0377 | TTY_QUOTE, * erase rest of word */ do { - ttyrub(c, tp); + if (ttyrub(c, tp)) + ret = 1; c = unputc(&tp->t_rawq); if (c == -1) goto endcase; @@ -509,7 +514,7 @@ parmrk: (void)putc(0377 | TTY_QUOTE, * reprint line (^R) */ if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) { - ttyretype(tp); + ret = ttyretype(tp); goto endcase; } /* @@ -576,12 +581,13 @@ endcase: */ if (ISSET(tp->t_state, TS_TTSTOP) && !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) - return (0); + return (ret); restartoutput: CLR(tp->t_lflag, FLUSHO); CLR(tp->t_state, TS_TTSTOP); startoutput: - return (ttstart(tp)); + ttstart(tp); + return (ret); } /* @@ -1882,7 +1888,7 @@ ovhiwat: * Rubout one character from the rawq of tp * as cleanly as possible. */ -void +int ttyrub(int c, struct tty *tp) { u_char *cp; @@ -1890,15 +1896,14 @@ ttyrub(int c, struct tty *tp) int tabc, s; if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) - return; + return 0; CLR(tp->t_lflag, FLUSHO); if (ISSET(tp->t_lflag, ECHOE)) { if (tp->t_rocount == 0) { /* * Screwed by ttwrite; retype */ - ttyretype(tp); - return; + return ttyretype(tp); } if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) ttyrubo(tp, 2); @@ -1917,10 +1922,8 @@ ttyrub(int c, struct tty *tp) ttyrubo(tp, 2); break; case TAB: - if (tp->t_rocount < tp->t_rawq.c_cc) { - ttyretype(tp); - return; - } + if (tp->t_rocount < tp->t_rawq.c_cc) + return ttyretype(tp); s = spltty(); savecol = tp->t_column; SET(tp->t_state, TS_CNTTB); @@ -1958,6 +1961,7 @@ ttyrub(int c, struct tty *tp) } else ttyecho(tp->t_cc[VERASE], tp); --tp->t_rocount; + return 0; } /* @@ -1979,7 +1983,7 @@ ttyrubo(struct tty *tp, int cnt) * Reprint the rawq line. Note, it is assumed that c_cc has already * been checked. */ -void +int ttyretype(struct tty *tp) { u_char *cp; @@ -2001,6 +2005,11 @@ ttyretype(struct tty *tp) tp->t_rocount = tp->t_rawq.c_cc; tp->t_rocol = 0; + /* + * Yield because of expense, or possible ptcwrite() injection flood. + * Also check for interrupt, and return upwards. + */ + return tsleep_nsec(tp, TTIPRI | PCATCH, "ttyretype", 1); } /* Index: sys/kern/tty_pty.c =================================================================== RCS file: /cvs/src/sys/kern/tty_pty.c,v diff -u -p -u -r1.98 tty_pty.c --- sys/kern/tty_pty.c 7 Apr 2020 13:27:51 -0000 1.98 +++ sys/kern/tty_pty.c 14 Jul 2020 14:35:42 -0000 @@ -564,7 +564,8 @@ again: wakeup(&tp->t_rawq); goto block; } - (*linesw[tp->t_line].l_rint)(*cp++, tp); + if ((*linesw[tp->t_line].l_rint)(*cp++, tp) == EINTR) + goto interrupt; cnt++; cc--; } @@ -591,6 +592,7 @@ block: if (error == 0) goto again; +interrupt: /* adjust for data copied in but not written */ uio->uio_resid += cc; done: