Re: PTY handling patch for 1.3.29

Theodore Ts'o (tytso@mit.edu)
Wed, 27 Sep 1995 16:14:19 -0400


From: Jeff Noxon <jeff@mrsagw.mrsa.com>
Date: Wed, 27 Sep 1995 10:54:07 -0500 (CDT)

About a month ago I posted to linux-kernel about a problem I was having with
the pty handling. The problem is that someone can telnet to a machine and
start an ill-behaved daemon process that inherits a slave pty, but
the master is released when the telnet session (or xterm or whatever)
is terminated. The open slave can cause problems for programs that try to
use that pty later.

What sort of problems are you seeing? When the master pty is closed,
the slave process receives a hangup, which should prevent programs from
being able to cause any problems with the pty.

Hmm.... this does could a potential problem if the master pty is opened
by, say, telnetd, before telnetd's child can open the slave side of the
pty. Because tty->link->count is non-zero, this would allow the open of
the master pty to return before the slave pty is opened. Not all
programs would be sensitive to this timing issue, which is probably why
we haven't noticed it before.

Thinking about this some more, this is probably the cause of some
intermittent problems I've had with the "script" command over the years,
which I've never been able to track down, and which happened rarely
enough so it was only a bother.....

Why don't you try this patch and see if it solves the problems on your
system? It's cleaner, and it allows a pty to be reused even if there
are processes that still have file descriptors open on the hungup slave
side of the pty. I think this should fix things for you, but the patch
has only been lightly tested. Let me know how it goes!

- Ted

--- drivers/char/pty.c 1995/09/27 19:57:39 1.1
+++ drivers/char/pty.c 1995/09/27 20:02:09
@@ -77,9 +77,10 @@
return;
wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait);
- if (tty->driver.subtype == PTY_TYPE_MASTER)
+ if (tty->driver.subtype == PTY_TYPE_MASTER) {
tty_hangup(tty->link);
- else {
+ set_bit(TTY_SLAVE_CLOSED, &tty->flags);
+ } else {
start_tty(tty);
set_bit(TTY_SLAVE_CLOSED, &tty->link->flags);
}
@@ -204,7 +205,8 @@
set_bit(TTY_THROTTLED, &tty->flags);
if (filp->f_flags & O_NDELAY)
return 0;
- while (!tty->link->count && !(current->signal & ~current->blocked))
+ while (test_bit(TTY_SLAVE_CLOSED, &tty->link->flags) &&
+ !(current->signal & ~current->blocked))
interruptible_sleep_on(&pty->open_wait);
if (!tty->link->count)
return -ERESTARTSYS;