Skip to content

Commit

Permalink
TTY: ldisc, wait for idle ldisc in release
Browse files Browse the repository at this point in the history
We reintroduced tty_ldisc_wait_idle in 100eeae (TTY: restore
tty_ldisc_wait_idle) and used in set_ldisc. Then we added it also to
the hangup path in 92f6fa0 (TTY: ldisc, do not close until there
are readers). And we noted that there is one more path:
~   Before 65b7704 tty_ldisc_wait_idle was called also from
~   tty_ldisc_release. It is called from tty_release, so I don't think
~   we need to restore that one.

Well, I was wrong. There might still be holders of an ldisc
reference. Not from userspace, but drivers. If they take a reference
and a user closes the device immediately after that, we have a
problem. ldisc is halted and closed by TTY, but the driver still may
call some ldisc's operation and cause a crash.

So restore the tty_ldisc_wait_idle call also to the third location
where it was before 65b7704 (tty-ldisc: turn ldisc user count
into a proper refcount). Now we should be safe with respect to the
ldisc reference counting as all* tty_ldisc_close paths are safely
called with reference count of one.

* Not the one in tty_ldisc_setup's fail path. But that is called
  before the first open finishes. So userspace does not see it yet.
  Even thought the driver is given the TTY already via ->install, it
  should not take a reference to the ldisc yet. If some driver is to
  do this, we should put one tty_ldisc_wait_idle also in the setup.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jiri Slaby authored and Greg Kroah-Hartman committed Oct 22, 2012
1 parent 7ee00fd commit 31e1212
Showing 1 changed file with 5 additions and 0 deletions.
5 changes: 5 additions & 0 deletions drivers/tty/tty_ldisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)

static void tty_ldisc_kill(struct tty_struct *tty)
{
/* There cannot be users from userspace now. But there still might be
* drivers holding a reference via tty_ldisc_ref. Do not steal them the
* ldisc until they are done. */
tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);

mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
Expand Down

0 comments on commit 31e1212

Please sign in to comment.