Skip to content

Commit

Permalink
[PATCH] tty reference count fix
Browse files Browse the repository at this point in the history
Fix hole where tty structure can be released when reference count is non
zero.  Existing code can sleep without tty_sem protection between deciding
to release the tty structure (setting local variables tty_closing and
otty_closing) and setting TTY_CLOSING to prevent further opens.  An open
can occur during this interval causing release_dev() to free the tty
structure while it is still referenced.

This should fix bugzilla.kernel.org [Bug 6041] New: Unable to handle kernel
paging request

In Bug 6041, tty_open() oopes on accessing the tty structure it has
successfully claimed.  Bug was on SMP machine with the same tty being
opened and closed by multiple processes, and DEBUG_PAGEALLOC enabled.

Signed-off-by: Paul Fulghum <paulkf@microgate.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Jesper Juhl <jesper.juhl@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Paul Fulghum authored and Linus Torvalds committed Feb 15, 2006
1 parent 16bf134 commit da96582
Showing 1 changed file with 3 additions and 4 deletions.
7 changes: 3 additions & 4 deletions drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1841,7 +1841,6 @@ static void release_dev(struct file * filp)
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
up(&tty_sem);
do_sleep = 0;

if (tty_closing) {
Expand Down Expand Up @@ -1869,6 +1868,7 @@ static void release_dev(struct file * filp)

printk(KERN_WARNING "release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
up(&tty_sem);
schedule();
}

Expand All @@ -1877,8 +1877,6 @@ static void release_dev(struct file * filp)
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
*/

down(&tty_sem);
if (pty_master) {
if (--o_tty->count < 0) {
printk(KERN_WARNING "release_dev: bad pty slave count "
Expand All @@ -1892,7 +1890,6 @@ static void release_dev(struct file * filp)
tty->count, tty_name(tty, buf));
tty->count = 0;
}
up(&tty_sem);

/*
* We've decremented tty->count, so we need to remove this file
Expand Down Expand Up @@ -1937,6 +1934,8 @@ static void release_dev(struct file * filp)
read_unlock(&tasklist_lock);
}

up(&tty_sem);

/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing))
return;
Expand Down

0 comments on commit da96582

Please sign in to comment.