summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaniel.starke@siemens.com <daniel.starke@siemens.com>2022-02-18 10:31:20 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-03-02 13:51:20 +0300
commitbcb96350dc2c645cae3da11047f803eb7ca678c4 (patch)
treef801339ebfdc15df6dd743c45f3b3800fb4ebd10
parentc559f05642e1615c052f377d39735a738418ef58 (diff)
downloadlinux-bcb96350dc2c645cae3da11047f803eb7ca678c4.tar.xz
tty: n_gsm: fix NULL pointer access due to DLCI release
commit 96b169f05cdcc844b400695184d77e42071d14f2 upstream. The here fixed commit made the tty hangup asynchronous to avoid a circular locking warning. I could not reproduce this warning. Furthermore, due to the asynchronous hangup the function call now gets queued up while the underlying tty is being freed. Depending on the timing this results in a NULL pointer access in the global work queue scheduler. To be precise in process_one_work(). Therefore, the previous commit made the issue worse which it tried to fix. This patch fixes this by falling back to the old behavior which uses a blocking tty hangup call before freeing up the associated tty. Fixes: 7030082a7415 ("tty: n_gsm: avoid recursive locking with async port hangup") Cc: stable@vger.kernel.org Signed-off-by: Daniel Starke <daniel.starke@siemens.com> Link: https://lore.kernel.org/r/20220218073123.2121-4-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/n_gsm.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index f57862ebafaa..b270659393e3 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1752,7 +1752,12 @@ static void gsm_dlci_release(struct gsm_dlci *dlci)
gsm_destroy_network(dlci);
mutex_unlock(&dlci->mutex);
- tty_hangup(tty);
+ /* We cannot use tty_hangup() because in tty_kref_put() the tty
+ * driver assumes that the hangup queue is free and reuses it to
+ * queue release_one_tty() -> NULL pointer panic in
+ * process_one_work().
+ */
+ tty_vhangup(tty);
tty_port_tty_set(&dlci->port, NULL);
tty_kref_put(tty);