linux/drivers/tty
Peter Hurley e7f3880cd9 tty: Fix recursive deadlock in tty_perform_flush()
tty_perform_flush() can deadlock when called while holding
a line discipline reference. By definition, all ldisc drivers
hold a ldisc reference, so calls originating from ldisc drivers
must not block for a ldisc reference.

The deadlock can occur when:
  CPU 0                    |  CPU 1
                           |
tty_ldisc_ref(tty)         |
....                       | <line discipline halted>
tty_ldisc_ref_wait(tty)    |
                           |

CPU 0 cannot progess because it cannot obtain an ldisc reference
with the line discipline has been halted (thus no new references
are granted).
CPU 1 cannot progress because an outstanding ldisc reference
has not been released.

An in-tree call-tree audit of tty_perform_flush() [1] shows 5
ldisc drivers calling tty_perform_flush() indirectly via
n_tty_ioctl_helper() and 2 ldisc drivers calling directly.
A single tty driver safely uses the function.

[1]
Recursive usage:

/* These functions are line discipline ioctls and thus
 * recursive wrt line discipline references */

tty_perform_flush() - ./drivers/tty/tty_ioctl.c
    n_tty_ioctl_helper()
        hci_uart_tty_ioctl(default) - drivers/bluetooth/hci_ldisc.c (N_HCI)
        n_hdlc_tty_ioctl(default) - drivers/tty/n_hdlc.c (N_HDLC)
        gsmld_ioctl(default) - drivers/tty/n_gsm.c (N_GSM0710)
        n_tty_ioctl(default) - drivers/tty/n_tty.c (N_TTY)
        gigaset_tty_ioctl(default) - drivers/isdn/gigaset/ser-gigaset.c (N_GIGASET_M101)
    ppp_synctty_ioctl(TCFLSH) - drivers/net/ppp/pps_synctty.c
    ppp_asynctty_ioctl(TCFLSH) - drivers/net/ppp/ppp_async.c

Non-recursive use:

tty_perform_flush() - drivers/tty/tty_ioctl.c
    ipw_ioctl(TCFLSH) - drivers/tty/ipwireless/tty.c
       /* This function is a tty i/o ioctl method, which
        * is invoked by tty_ioctl() */

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18 16:52:24 -07:00
..
hvc TTY: add tty_port_tty_wakeup helper 2013-03-18 16:19:45 -07:00
ipwireless tty: ipwireless: Remove redundant NULL check before kfree 2013-03-15 13:58:32 -07:00
serial tty: ifx6x60: Remove unused suspend/resume callbacks 2013-03-18 16:29:29 -07:00
vt Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
amiserial.c TTY: amiserial, use module_platform_driver_probe() 2013-03-15 13:55:23 -07:00
bfin_jtag_comm.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
cyclades.c TTY: add tty_port_tty_hangup helper 2013-03-18 16:24:29 -07:00
ehv_bytechan.c TTY: add tty_port_tty_wakeup helper 2013-03-18 16:19:45 -07:00
goldfish.c goldfish: move to tty_port for flip buffers 2013-01-25 08:09:38 -08:00
isicom.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
Kconfig tty: metag_da: Add metag DA TTY driver 2013-02-06 11:10:17 -08:00
Makefile tty: metag_da: Add metag DA TTY driver 2013-02-06 11:10:17 -08:00
metag_da.c tty: metag_da: avoid getting tty kref in dashtty_timer() 2013-02-06 11:10:17 -08:00
moxa.c TTY: add tty_port_tty_hangup helper 2013-03-18 16:24:29 -07:00
moxa.h
mxser.c TTY: fix DTR not being dropped on hang up 2013-03-18 16:27:53 -07:00
mxser.h
n_gsm.c TTY: fix DTR not being dropped on hang up 2013-03-18 16:27:53 -07:00
n_hdlc.c
n_r3964.c tty: localise the lock 2012-08-10 12:55:47 -07:00
n_tracerouter.c
n_tracesink.c
n_tracesink.h
n_tty.c n_tty: Fully initialize ldisc before restarting buffer work 2013-03-18 16:44:01 -07:00
nozomi.c TTY: add tty_port_tty_hangup helper 2013-03-18 16:24:29 -07:00
pty.c pty: Remove redundant itty reset 2013-03-15 13:00:48 -07:00
rocket_int.h
rocket.c TTY: cleanup tty->hw_stopped uses 2013-03-18 16:24:30 -07:00
rocket.h
synclink_gt.c TTY: synclink: Convert + to | for bit operations 2013-01-30 00:09:58 -05:00
synclink.c TTY: synclink, remove superfluous check 2013-03-18 16:17:20 -07:00
synclinkmp.c TTY: synclink: Convert + to | for bit operations 2013-01-30 00:09:58 -05:00
sysrq.c sysrq: fix inconstistent help message of sysrq key 2013-03-15 14:06:45 -07:00
tty_audit.c TTY: audit, stop accessing tty->icount 2012-10-22 16:50:54 -07:00
tty_buffer.c pps: Move timestamp read into PPS code proper 2013-02-13 10:13:58 -08:00
tty_io.c tty: Don't protect atomic operation with mutex 2013-03-18 16:46:31 -07:00
tty_ioctl.c tty: Fix recursive deadlock in tty_perform_flush() 2013-03-18 16:52:24 -07:00
tty_ldisc.c tty: Remove redundant tty_wait_until_sent() 2013-03-18 16:48:42 -07:00
tty_mutex.c tty: tty_mutex.c: Fixed coding style warning (using printk) 2012-10-24 11:34:51 -07:00
tty_port.c tty: Complete ownership transfer of flip buffers 2013-03-18 16:44:02 -07:00