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/