possible pty DoS
Subsystems (2)
hello all
I am not subscribed to linux-kernel*; please CC any follow-ups to [email protected] (I probably won't reply from 2000-12-22 to 2001-01-07)
I am running 2.4.0-test12-pre2
This snippet can prevent progress of any other processes that tries to do a write to a pty:
============
#include <sys/fcntl.h>
#include <unistd.h>
int main()
{
int ptm;
ptm = open("/dev/ptmx", O_WRONLY);
while (1)
write(ptm, "hello, world!\n", 14);
}============
With this running, and no process eating up the greetings, I can telnet to my machine; the banner and login prompt appear. ps -alx at this point reveals in.telnetd is in do_select(). As soon as I type even one char of username, another ps reveals in.telnetd now stuck in __down_interruptible()
Lucky I usually leave a few logged in consoles lying around; xterm also uses pty's!
Some observations:
2.2.12 behaves fine (telnet logins work fine)
2.2.12-2.4.0 diffs between tty_io.c show changes involving up/down/etc. in do_tty_write().
Bernd JendrissekP.S. apologies to all for my void * arithmetic a few months ago; it was a moment of eager-beaver weakness.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
This 2.4 bug must be fixed.
Quoted 15 lines · [email protected] wrote:
This snippet can prevent progress of any other processes that tries to do a write to a pty:
============
#include <sys/fcntl.h> #include <unistd.h> int main() { int ptm; ptm = open("/dev/ptmx", O_WRONLY); while (1) write(ptm, "hello, world!\n", 14); }
Quoted 2 lines
============
Your program fills up the pty write buffer and then blocks. This is fair enough. But it blocks while holding the /dev/ptmx inode semaphore, so _all_ other users of /dev/ptmx are blocked. Your xterms get stuck, telnet and ssh are dead. It's time to find the car keys.
In 2.2, we have a per-tty semaphore. No problems. This patch basically restores the 2.2 implementation and it passes basic sanity testing.
But it's not my area. Is there really a _need_ to take the inode semaphore while we're writing to the pty instance? I hope not, because I took that out.
Perhaps it would be logical to clone the /dev/ptmx inode in some manner when it's opened?
Anyone?
include/linux/tty.h +1 -0
@@ -305,6 +305,7 @@unsigned long canon_head;unsigned int canon_column;struct semaphore atomic_read; +struct semaphore atomic_write;spinlock_t read_lock; };
drivers/char/tty_io.c +3 -3
@@ -699,9 +699,8 @@ size_t count) {ssize_t ret =0 , written =0 ; -struct inode *inode = file->f_dentry->d_inode; -if (down_interruptible (&inode->i_sem)) { +if (down_interruptible (&tty->atomic_write)) {return -ERESTARTSYS ; }if (test_bit (TTY_NO_WRITE_SPLIT , &tty->flags) ) {
@@ -734,7 +733,7 @@ file->f_dentry->d_inode->i_mtime =CURRENT_TIME ; ret = written; } -up (&inode->i_sem); +up (&tty->atomic_write);return ret; }
@@ -1972,6 +1971,7 @@ tty->tq_hangup.routine = do_tty_hangup; tty->tq_hangup.data = tty;sema_init (&tty->atomic_read,1 ); +sema_init (&tty->atomic_write,1 );spin_lock_init (&tty->read_lock);INIT_LIST_HEAD (&tty->tty_files); }
-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/