]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
tty: n_gsm: fix mux cleanup after unregister tty device
authorDaniel Starke <daniel.starke@siemens.com>
Thu, 14 Apr 2022 09:42:09 +0000 (02:42 -0700)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 22 Jun 2022 12:23:04 +0000 (14:23 +0200)
BugLink: https://bugs.launchpad.net/bugs/1978234
commit 284260f278b706364fb4c88a7b56ba5298d5973c upstream.

Internally, we manage the alive state of the mux channels and mux itself
with the field member 'dead'. This makes it possible to notify the user
if the accessed underlying link is already gone. On the other hand,
however, removing the virtual ttys before terminating the channels may
result in peer messages being received without any internal target. Move
the mux cleanup procedure from gsmld_detach_gsm() to gsmld_close() to fix
this by keeping the virtual ttys open until the mux has been cleaned up.

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/20220414094225.4527-4-daniel.starke@siemens.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/tty/n_gsm.c

index 2858b516ff3fb90629ed42af6bfa0e4eadb75327..1ffb27ca02027c57263564c83f10a78fcf1e3ad6 100644 (file)
@@ -2418,7 +2418,6 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
        WARN_ON(tty != gsm->tty);
        for (i = 1; i < NUM_DLCI; i++)
                tty_unregister_device(gsm_tty_driver, base + i);
-       gsm_cleanup_mux(gsm, false);
        tty_kref_put(gsm->tty);
        gsm->tty = NULL;
 }
@@ -2483,6 +2482,12 @@ static void gsmld_close(struct tty_struct *tty)
 {
        struct gsm_mux *gsm = tty->disc_data;
 
+       /* The ldisc locks and closes the port before calling our close. This
+        * means we have no way to do a proper disconnect. We will not bother
+        * to do one.
+        */
+       gsm_cleanup_mux(gsm, false);
+
        gsmld_detach_gsm(tty, gsm);
 
        gsmld_flush_buffer(tty);