linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "D. Starke" <daniel.starke@siemens.com>
To: linux-serial@vger.kernel.org, gregkh@linuxfoundation.org,
	jirislaby@kernel.org
Cc: linux-kernel@vger.kernel.org, Daniel Starke <daniel.starke@siemens.com>
Subject: [PATCH 03/20] tty: n_gsm: fix decoupled mux resource
Date: Thu, 14 Apr 2022 02:42:08 -0700	[thread overview]
Message-ID: <20220414094225.4527-3-daniel.starke@siemens.com> (raw)
In-Reply-To: <20220414094225.4527-1-daniel.starke@siemens.com>

From: Daniel Starke <daniel.starke@siemens.com>

The active mux instances are managed in the gsm_mux array and via mux_get()
and mux_put() functions separately. This gives a very loose coupling
between the actual instance and the gsm_mux array which manages it. It also
results in unnecessary lockings which makes it prone to failures. And it
creates a race condition if more than the maximum number of mux instances
are requested while the user changes the parameters of an active instance.
The user may loose ownership of the current mux instance in this case.
Fix this by moving the gsm_mux array handling to the mux allocation and
deallocation functions.

Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Starke <daniel.starke@siemens.com>
---
 drivers/tty/n_gsm.c | 63 +++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index daaffcfadaae..f546dfe03d29 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2136,18 +2136,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 	/* Finish outstanding timers, making sure they are done */
 	del_timer_sync(&gsm->t2_timer);
 
-	spin_lock(&gsm_mux_lock);
-	for (i = 0; i < MAX_MUX; i++) {
-		if (gsm_mux[i] == gsm) {
-			gsm_mux[i] = NULL;
-			break;
-		}
-	}
-	spin_unlock(&gsm_mux_lock);
-	/* open failed before registering => nothing to do */
-	if (i == MAX_MUX)
-		return;
-
 	/* Free up any link layer users */
 	for (i = 0; i < NUM_DLCI; i++)
 		if (gsm->dlci[i])
@@ -2171,7 +2159,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 static int gsm_activate_mux(struct gsm_mux *gsm)
 {
 	struct gsm_dlci *dlci;
-	int i = 0;
 
 	timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
 	init_waitqueue_head(&gsm->event);
@@ -2183,18 +2170,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
 	else
 		gsm->receive = gsm1_receive;
 
-	spin_lock(&gsm_mux_lock);
-	for (i = 0; i < MAX_MUX; i++) {
-		if (gsm_mux[i] == NULL) {
-			gsm->num = i;
-			gsm_mux[i] = gsm;
-			break;
-		}
-	}
-	spin_unlock(&gsm_mux_lock);
-	if (i == MAX_MUX)
-		return -EBUSY;
-
 	dlci = gsm_dlci_alloc(gsm, 0);
 	if (dlci == NULL)
 		return -ENOMEM;
@@ -2210,6 +2185,15 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
  */
 static void gsm_free_mux(struct gsm_mux *gsm)
 {
+	int i;
+
+	for (i = 0; i < MAX_MUX; i++) {
+		if (gsm == gsm_mux[i]) {
+			gsm_mux[i] = NULL;
+			break;
+		}
+	}
+	mutex_destroy(&gsm->mutex);
 	kfree(gsm->txframe);
 	kfree(gsm->buf);
 	kfree(gsm);
@@ -2229,12 +2213,20 @@ static void gsm_free_muxr(struct kref *ref)
 
 static inline void mux_get(struct gsm_mux *gsm)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&gsm_mux_lock, flags);
 	kref_get(&gsm->ref);
+	spin_unlock_irqrestore(&gsm_mux_lock, flags);
 }
 
 static inline void mux_put(struct gsm_mux *gsm)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&gsm_mux_lock, flags);
 	kref_put(&gsm->ref, gsm_free_muxr);
+	spin_unlock_irqrestore(&gsm_mux_lock, flags);
 }
 
 static inline unsigned int mux_num_to_base(struct gsm_mux *gsm)
@@ -2255,6 +2247,7 @@ static inline unsigned int mux_line_to_num(unsigned int line)
 
 static struct gsm_mux *gsm_alloc_mux(void)
 {
+	int i;
 	struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL);
 	if (gsm == NULL)
 		return NULL;
@@ -2284,6 +2277,26 @@ static struct gsm_mux *gsm_alloc_mux(void)
 	gsm->mtu = 64;
 	gsm->dead = true;	/* Avoid early tty opens */
 
+	/* Store the instance to the mux array or abort if no space is
+	 * available.
+	 */
+	spin_lock(&gsm_mux_lock);
+	for (i = 0; i < MAX_MUX; i++) {
+		if (!gsm_mux[i]) {
+			gsm_mux[i] = gsm;
+			gsm->num = i;
+			break;
+		}
+	}
+	spin_unlock(&gsm_mux_lock);
+	if (i == MAX_MUX) {
+		mutex_destroy(&gsm->mutex);
+		kfree(gsm->txframe);
+		kfree(gsm->buf);
+		kfree(gsm);
+		return NULL;
+	}
+
 	return gsm;
 }
 
-- 
2.25.1


  parent reply	other threads:[~2022-04-14  9:44 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-14  9:42 [PATCH 01/20] tty: n_gsm: fix missing mux reset on config change at responder D. Starke
2022-04-14  9:42 ` [PATCH 02/20] tty: n_gsm: fix restart handling via CLD command D. Starke
2022-04-14  9:42 ` D. Starke [this message]
2022-04-14  9:42 ` [PATCH 04/20] tty: n_gsm: fix mux cleanup after unregister tty device D. Starke
2022-04-14  9:42 ` [PATCH 05/20] tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2 D. Starke
2022-04-14  9:42 ` [PATCH 06/20] tty: n_gsm: fix frame reception handling D. Starke
2022-04-14  9:42 ` [PATCH 07/20] tty: n_gsm: fix malformed counter for out of frame data D. Starke
2022-04-14  9:42 ` [PATCH 08/20] tty: n_gsm: fix insufficient txframe size D. Starke
2022-04-14  9:42 ` [PATCH 09/20] tty: n_gsm: fix wrong DLCI release order D. Starke
2022-04-14  9:42 ` [PATCH 10/20] tty: n_gsm: fix missing explicit ldisc flush D. Starke
2022-04-14  9:42 ` [PATCH 11/20] tty: n_gsm: fix wrong command retry handling D. Starke
2022-04-14  9:42 ` [PATCH 12/20] tty: n_gsm: fix wrong command frame length field encoding D. Starke
2022-04-14  9:42 ` [PATCH 13/20] tty: n_gsm: fix wrong signal octets encoding in MSC D. Starke
2022-04-14  9:42 ` [PATCH 14/20] tty: n_gsm: fix missing tty wakeup in convergence layer type 2 D. Starke
2022-04-14  9:42 ` [PATCH 15/20] tty: n_gsm: fix missing update of modem controls after DLCI open D. Starke
2022-04-15  6:29   ` Greg KH
2022-04-19  8:07     ` [PATCH v2 " D. Starke
2022-04-19 10:07       ` Greg KH
2022-04-14  9:42 ` [PATCH 16/20] tty: n_gsm: fix invalid command/response bit check for UI/UIH frames D. Starke
2022-04-15  6:31   ` Greg KH
2022-04-19  8:17     ` [PATCH v2 16/20] tty: n_gsm: clean up dead code in gsm_queue() D. Starke
2022-04-19 10:06       ` Greg KH
2022-04-19 10:07       ` Greg KH
2022-04-14  9:42 ` [PATCH 17/20] tty: n_gsm: fix reset fifo race condition D. Starke
2022-04-14  9:42 ` [PATCH 18/20] tty: n_gsm: fix implicit CR bit encoding in address field D. Starke
2022-04-15  6:33   ` Greg KH
2022-04-19  8:19     ` [PATCH v2 18/20] tty: n_gsm: clean up " D. Starke
2022-04-19 10:06       ` Greg KH
2022-04-14  9:42 ` [PATCH 19/20] tty: n_gsm: fix wrong behavior of gsm_carrier_raised() on debug D. Starke
2022-04-15  6:34   ` Greg KH
2022-04-14  9:42 ` [PATCH 20/20] tty: n_gsm: fix incorrect UA handling D. Starke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220414094225.4527-3-daniel.starke@siemens.com \
    --to=daniel.starke@siemens.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).