Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp1220067iob; Wed, 4 May 2022 17:51:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzCapeW170IC8xc9m+xCPLBTB8tiaRx+ga0GAlYyebdTLK0A3Khps0U6mFmAlsWqX/9Bq35 X-Received: by 2002:aa7:9846:0:b0:50d:d690:4af4 with SMTP id n6-20020aa79846000000b0050dd6904af4mr21082762pfq.58.1651711913221; Wed, 04 May 2022 17:51:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651711913; cv=none; d=google.com; s=arc-20160816; b=P0s9d7Us5QL+Sq4FB5hSEDyCR+JPdaPjw7vLUMXccZdNlSYPW9qYEbdrZVy4CP2qbR fx57HM5DjEcAbp8HP7lV6uI47En0ocK87RpfA69S5mOyJWBQ+OGrqnnsV/by836GnjdX AJ980tGImOGD9IisNUXUZZyBZbA1XSO6WKkP0ZrWQoxFb1dmEesvfN1j/oJsZqQwUyyq 2HWNoh/XsBNoY+++oLeQCqf4y7vaiHrSaFnVpkp4vcyzppm7nubC8vE6/GoLsBGspjXX 5WSQvSoZRiuPZM+GkXDlgSw+2i5VhqSouYm9MJwoQpd7wLmZ3mTWKwa6ZJ4wqiLGpz4d BF/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=q8ELKenjENUCbZsrW2xRmCMKjE1CiLNIVFWtUjDmcto=; b=d4uh28EByqGUJ/N6tYpj1SGWZ3BhLARA2fJlgFDzPjL2Iee/yCf5eIVL/ceW45LQn5 RszsAzFXyMqsOs+2iVtY8l7hA8nAYrHwirHm0UeP4j9OCWDX/iyewPmO5QBWlpMUfXZq 84VVJaGni9EfsBUG4NbFGlEcOg0JGyPHHQiRrRYiVYUIDAtVK2wi5Phtil3Ybw+a8x4E K2REHBv4x/7j8m6Lwlb8fzW2z+l6+qTKSxuj/Lcae3PKsQxs4QhTeIgfJxXlAuyvgPgz qFHiGydCIontUbimZ3R+thKb8swOt+SB6EtdkKS4Uy4aJI0i8NYnCB7KkUBIdU27jVO1 EbEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hkTGBT+R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g3-20020a056a0023c300b0050d51c28264si80665pfc.68.2022.05.04.17.51.38; Wed, 04 May 2022 17:51:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hkTGBT+R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357669AbiEDR3I (ORCPT + 99 others); Wed, 4 May 2022 13:29:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356268AbiEDRJI (ORCPT ); Wed, 4 May 2022 13:09:08 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9894D532D1; Wed, 4 May 2022 09:55:02 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C85DF617BD; Wed, 4 May 2022 16:55:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A18DC385A5; Wed, 4 May 2022 16:55:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1651683301; bh=6bZU3NGMInlfBN8tBdB3M1+GwC8lMtxZ9yWkud+oP+c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hkTGBT+R+uolJZMKsdGMfP4ZQZaV0FivSr3H5l91rCWoiHjW4PYUNzOn6xszwjoE+ lngMc4Ci8mDt578YlxLIUlNXps2bAQT3R4PiWiQyjCV/mNi17qYX3ByB81svRMKjnX uH8xfTYt3TRJkJ9cBnNiLhFQONJphpxTo6J7o5lY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Starke Subject: [PATCH 5.15 158/177] tty: n_gsm: fix decoupled mux resource Date: Wed, 4 May 2022 18:45:51 +0200 Message-Id: <20220504153107.599944026@linuxfoundation.org> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504153053.873100034@linuxfoundation.org> References: <20220504153053.873100034@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Daniel Starke commit 1ec92e9742774bf42614fceea3bf6b50c9409225 upstream. 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 Link: https://lore.kernel.org/r/20220414094225.4527-3-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 63 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 25 deletions(-) --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2078,18 +2078,6 @@ static void gsm_cleanup_mux(struct gsm_m /* 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]) @@ -2113,7 +2101,6 @@ static void gsm_cleanup_mux(struct gsm_m 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); @@ -2125,18 +2112,6 @@ static int gsm_activate_mux(struct gsm_m 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; @@ -2152,6 +2127,15 @@ static int gsm_activate_mux(struct gsm_m */ 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); @@ -2171,12 +2155,20 @@ static void gsm_free_muxr(struct kref *r 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) @@ -2197,6 +2189,7 @@ static inline unsigned int mux_line_to_n 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; @@ -2226,6 +2219,26 @@ static struct gsm_mux *gsm_alloc_mux(voi 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; }