提交 0bb292ee 编写于 作者: D Daniel Starke 提交者: Zheng Zengkai

tty: n_gsm: fix user open not possible at responder until initiator open

stable inclusion
from stable-v5.10.137
commit c45b5d24fe06e3c43794309559635909b3e0bdf6
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I60PLB

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c45b5d24fe06e3c43794309559635909b3e0bdf6

--------------------------------

[ Upstream commit ac77f007 ]

After setting up the control channel on both sides the responder side may
want to open a virtual tty to listen on until the initiator starts an
application on a user channel. The current implementation allows the
open() but no other operation, like termios. These fail with EINVAL.
The responder sided application has no means to detect an open by the
initiator sided application this way. And the initiator sided applications
usually expect the responder sided application to listen on the user
channel upon open.
Set the user channel into half-open state on responder side once a user
application opens the virtual tty to allow IO operations on it.
Furthermore, keep the user channel constipated until the initiator side
opens it to give the responder sided application the chance to detect the
new connection and to avoid data loss if the responder sided application
starts sending before the user channel is open.

Fixes: e1eaea46 ("tty: n_gsm line discipline")
Signed-off-by: NDaniel Starke <daniel.starke@siemens.com>
Link: https://lore.kernel.org/r/20220701061652.39604-1-daniel.starke@siemens.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 f10671a7
...@@ -1429,6 +1429,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) ...@@ -1429,6 +1429,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
if (debug & 8) if (debug & 8)
pr_debug("DLCI %d goes closed.\n", dlci->addr); pr_debug("DLCI %d goes closed.\n", dlci->addr);
dlci->state = DLCI_CLOSED; dlci->state = DLCI_CLOSED;
/* Prevent us from sending data before the link is up again */
dlci->constipated = true;
if (dlci->addr != 0) { if (dlci->addr != 0) {
tty_port_tty_hangup(&dlci->port, false); tty_port_tty_hangup(&dlci->port, false);
spin_lock_irqsave(&dlci->lock, flags); spin_lock_irqsave(&dlci->lock, flags);
...@@ -1458,6 +1460,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) ...@@ -1458,6 +1460,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
del_timer(&dlci->t1); del_timer(&dlci->t1);
/* This will let a tty open continue */ /* This will let a tty open continue */
dlci->state = DLCI_OPEN; dlci->state = DLCI_OPEN;
dlci->constipated = false;
if (debug & 8) if (debug & 8)
pr_debug("DLCI %d goes open.\n", dlci->addr); pr_debug("DLCI %d goes open.\n", dlci->addr);
wake_up(&dlci->gsm->event); wake_up(&dlci->gsm->event);
...@@ -1535,6 +1538,25 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci) ...@@ -1535,6 +1538,25 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci)
mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
} }
/**
* gsm_dlci_set_opening - change state to opening
* @dlci: DLCI to open
*
* Change internal state to wait for DLCI open from initiator side.
* We set off timers and responses upon reception of an SABM.
*/
static void gsm_dlci_set_opening(struct gsm_dlci *dlci)
{
switch (dlci->state) {
case DLCI_CLOSED:
case DLCI_CLOSING:
dlci->state = DLCI_OPENING;
break;
default:
break;
}
}
/** /**
* gsm_dlci_begin_close - start channel open procedure * gsm_dlci_begin_close - start channel open procedure
* @dlci: DLCI to open * @dlci: DLCI to open
...@@ -1673,10 +1695,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) ...@@ -1673,10 +1695,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
dlci->addr = addr; dlci->addr = addr;
dlci->adaption = gsm->adaption; dlci->adaption = gsm->adaption;
dlci->state = DLCI_CLOSED; dlci->state = DLCI_CLOSED;
if (addr) if (addr) {
dlci->data = gsm_dlci_data; dlci->data = gsm_dlci_data;
else /* Prevent us from sending data before the link is up */
dlci->constipated = true;
} else {
dlci->data = gsm_dlci_command; dlci->data = gsm_dlci_command;
}
gsm->dlci[addr] = dlci; gsm->dlci[addr] = dlci;
return dlci; return dlci;
} }
...@@ -3036,6 +3061,8 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) ...@@ -3036,6 +3061,8 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
/* Start sending off SABM messages */ /* Start sending off SABM messages */
if (gsm->initiator) if (gsm->initiator)
gsm_dlci_begin_open(dlci); gsm_dlci_begin_open(dlci);
else
gsm_dlci_set_opening(dlci);
/* And wait for virtual carrier */ /* And wait for virtual carrier */
return tty_port_block_til_ready(port, tty, filp); return tty_port_block_til_ready(port, tty, filp);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册