Linus Torvalds 5c58ceff10 tty: make sure to flush any pending work when halting the ldisc
When I rewrote tty ldisc code to use proper reference counts (commits
65b770468e98 and cbe9352fa08f) in order to avoid a race with hangup, the
test-program that Eric Biederman used to trigger the original problem
seems to have exposed another long-standing bug: the hangup code did the
'tty_ldisc_halt()' to stop any buffer flushing activity, but unlike the
other call sites it never actually flushed any pending work.

As a result, if you get just the right timing, the pending work may be
just about to execute (ie the timer has already triggered and thus
cancel_delayed_work() was a no-op), when we then re-initialize the ldisc
from under it.

That, in turn, results in various random problems, usually seen as a
NULL pointer dereference in run_timer_softirq() or a BUG() in
worker_thread (but it can be almost anything).

Fix it by adding the required 'flush_scheduled_work()' after doing the
tty_ldisc_halt() (this also requires us to move the ldisc halt to before
taking the ldisc mutex in order to avoid a deadlock with the workqueue
executing do_tty_hangup, which requires the mutex).

The locking should be cleaned up one day (the requirement to do this
outside the ldisc_mutex is very annoying, and weakens the lock), but
that's a larger and separate undertaking.

Reported-by: Eric W. Biederman <ebiederm@xmission.com>
Tested-by: Xiaotian Feng <xtfeng@gmail.com>
Tested-by: Yanmin Zhang <yanmin_zhang@linux.intel.com>
Tested-by: Dave Young <hidave.darkstar@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-08-25 09:12:43 -07:00
..
2009-06-11 08:51:01 -07:00
2009-07-20 16:38:43 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2008-06-20 14:05:55 -06:00
2008-12-13 11:25:49 -08:00
2009-07-12 12:22:34 -07:00
2008-10-20 08:52:41 -07:00
2008-12-13 09:12:07 +00:00
2009-06-19 16:46:06 -07:00
2009-07-12 12:22:34 -07:00
2008-07-20 17:12:36 -07:00
2009-04-07 08:31:03 -07:00
2008-06-20 14:05:57 -06:00
2009-07-20 16:38:43 -07:00
2009-06-18 11:16:55 +10:00
2009-01-02 10:28:32 -08:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2008-06-20 14:05:48 -06:00
2009-07-12 12:22:34 -07:00
2008-07-24 10:47:14 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-20 16:38:43 -07:00
2009-06-18 13:03:54 -07:00
2009-08-10 13:31:18 -07:00
2009-07-12 12:22:34 -07:00
2008-07-20 17:12:38 -07:00
2009-07-12 12:22:34 -07:00
2009-01-08 16:44:03 -07:00
2009-02-22 09:23:02 -08:00
2009-06-11 08:51:01 -07:00
2009-07-12 12:22:34 -07:00
2009-03-16 08:34:35 -06:00
2008-07-20 17:12:38 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-29 19:10:36 -07:00
2009-07-03 15:45:29 +01:00
2008-06-20 14:05:51 -06:00
2008-04-30 23:15:34 +02:00
2009-06-11 08:51:02 -07:00
2009-06-16 12:01:16 -07:00
2009-07-12 12:22:34 -07:00
2009-07-12 12:22:34 -07:00
2009-07-16 09:19:16 -07:00