summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaniel.starke@siemens.com <daniel.starke@siemens.com>2022-02-18 10:31:23 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-03-02 13:51:21 +0300
commitbb8c499ff8a5d3b45a941e403b5eedb27c625cab (patch)
tree738c103a5fe86ad12830306aa20371cfa7c9d3c2
parent822c6ed263f83925ecc95d1ac88a07c74197681e (diff)
downloadlinux-bb8c499ff8a5d3b45a941e403b5eedb27c625cab.tar.xz
tty: n_gsm: fix deadlock in gsmtty_open()
commit a2ab75b8e76e455af7867e3835fd9cdf386b508f upstream. In the current implementation the user may open a virtual tty which then could fail to establish the underlying DLCI. The function gsmtty_open() gets stuck in tty_port_block_til_ready() while waiting for a carrier rise. This happens if the remote side fails to acknowledge the link establishment request in time or completely. At some point gsm_dlci_close() is called to abort the link establishment attempt. The function tries to inform the associated virtual tty by performing a hangup. But the blocking loop within tty_port_block_til_ready() is not informed about this event. The patch proposed here fixes this by resetting the initialization state of the virtual tty to ensure the loop exits and triggering it to make tty_port_block_til_ready() return. Fixes: e1eaea46bb40 ("tty: n_gsm line discipline") Cc: stable@vger.kernel.org Signed-off-by: Daniel Starke <daniel.starke@siemens.com> Link: https://lore.kernel.org/r/20220218073123.2121-7-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/n_gsm.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 0fc569521821..2ec9eeaabac9 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1457,6 +1457,9 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
if (dlci->addr != 0) {
tty_port_tty_hangup(&dlci->port, false);
kfifo_reset(&dlci->fifo);
+ /* Ensure that gsmtty_open() can return. */
+ tty_port_set_initialized(&dlci->port, 0);
+ wake_up_interruptible(&dlci->port.open_wait);
} else
dlci->gsm->dead = true;
/* Unregister gsmtty driver,report gsmtty dev remove uevent for user */