[PATCH] N_TTY may block out TQUEUE_BH for too long

Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
16 Nov 1998 11:33:26 +0100


When reading from an N_TTY line the timer task queue can be blocked out
for a long time. The problem is that read_chan calls put_user and
copy_to_user while TQUEUE_BH is disabled, and those calls can sleep.

Also, i think that copy_from_read_buf has a race condition: what if
another process starts reading from the same tty while copy_to_user
sleeps? It seems that tty->read_cnt can get negative in this case, which
would be very bad.

--- drivers/char/n_tty.c.~1~ Fri Nov 13 18:04:45 1998
+++ drivers/char/n_tty.c Fri Nov 13 20:52:40 1998
@@ -853,7 +853,9 @@
retval = 0;
n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
if (n) {
+ enable_bh(TQUEUE_BH);
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+ disable_bh(TQUEUE_BH);
n -= retval;
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
@@ -927,11 +929,15 @@
while (nr) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
+ unsigned char cs;
if (b != buf)
break;
- put_user(tty->link->ctrl_status, b++);
- nr--;
+ cs = tty->link->ctrl_status;
tty->link->ctrl_status = 0;
+ enable_bh(TQUEUE_BH);
+ put_user(cs, b++);
+ disable_bh(TQUEUE_BH);
+ nr--;
break;
}
/* This statement must be first before checking for input
@@ -969,7 +975,9 @@

/* Deal with packet mode. */
if (tty->packet && b == buf) {
+ enable_bh(TQUEUE_BH);
put_user(TIOCPKT_DATA, b++);
+ disable_bh(TQUEUE_BH);
nr--;
}

@@ -986,7 +994,9 @@
tty->read_cnt--;

if (!eol || (c != __DISABLED_CHAR)) {
+ enable_bh(TQUEUE_BH);
put_user(c, b++);
+ disable_bh(TQUEUE_BH);
nr--;
}
if (eol) {

-- 
Andreas Schwab                                      "And now for something
schwab@issan.cs.uni-dortmund.de                      completely different"
schwab@gnu.org

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/