Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp1143705iob; Wed, 4 May 2022 15:51:43 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyzg8rkiWEtSzsCnitkNFHcxf7yuIJSC8gllU24OQZGYMTOH3jqRJHQoxVCX9/iaPu8eb7i X-Received: by 2002:a17:906:86d3:b0:6f3:be23:7ad5 with SMTP id j19-20020a17090686d300b006f3be237ad5mr22897312ejy.264.1651704703701; Wed, 04 May 2022 15:51:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651704703; cv=none; d=google.com; s=arc-20160816; b=g8VtnwVKEow6ILq5nrPwIMG7oWLG2pjKz7KyfQ0eu1ag2SBWshrsR9NMVpMl3vneWS P25vwiAjLuLM8r7baWtDrLKgUJKN+GQwkXzBdbil9puZmg7m3+U+I4YRcQRIpW7/Ip/3 VqYoncXQOylF4wiUOpEvzXnf7tWNrL571JT9tqb4EAAGj1NBxptd4QKQ39H3SFs7/qbq 3r0snrwPzXc45Cncb5hSnPBkMDq/1WhnJiI8MrOBJCaD7a20eltZYL1PmgPp8pcM1C6q Qyv7f4ukS7O3GWMVSR4SKnEQeKKbCI/ej+goAWKHbFTYm5cOCof0OjbBGjBezUo+UB9b RTPA== 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=FOwtDuFwOGNZDiVhUFg0+2DByLibhz3dTeiyI9PwFXc=; b=d7h6zpGGe8aeamLrG2Mzq8o/nEKcPUcGKKlkX3MbsvLNx1jMmUZFHfmgY9WKgFAj5M lB+209hABpvBn2U5SZlJue1LHL/uNg23KqIMY550oxSuYDCfY0wirkGG3UQwb8VarM6N V2sBwsCDEddqFvn0T0sjlr/PVuG9RYupIf/lILKQLqEkE+k+4ZYMDRTanzMIdK6BwcLK 79Yp/PEBhiqppkayfSUmA5BM3uCoc8a/a/Wx+n7MxKpcicvr7hvvACl4om8u2csFs5wQ hf1qMc66Qevfc27nVGG8jHjqWmHiA/XqgdNZpaq6gNUY4/2xAor4tbckTkJzzpYSTR4x iBmg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="P/cbRVyT"; 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 hr24-20020a1709073f9800b006f435a2d1d7si254398ejc.483.2022.05.04.15.51.20; Wed, 04 May 2022 15:51:43 -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="P/cbRVyT"; 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 S1356319AbiEDRwq (ORCPT + 99 others); Wed, 4 May 2022 13:52:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55678 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1358300AbiEDRPt (ORCPT ); Wed, 4 May 2022 13:15:49 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8DE256771; Wed, 4 May 2022 09:59:37 -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 E5D7A61950; Wed, 4 May 2022 16:59:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A1461C385AA; Wed, 4 May 2022 16:59:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1651683549; bh=AOBz04IO0x5NuUMMvvLUKJriVH5uBAjA6v8SLusB+VI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P/cbRVyTX66nCFedUKfQ2sQ22KrWV1XK2EvMZdry58YpKhsEe4NkXjTiG+NYKCUII 46qdWrt+k2hd7tuxQm5vXCJ7nyLswYU/GcOiyhdJZ15ez1bwatAn6bEzUJI2KzH5nx Iy/kzz9j0g+q2gUM2+TJrpizq95dAu35AYpd9g/c= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Starke Subject: [PATCH 5.17 203/225] tty: n_gsm: fix decoupled mux resource Date: Wed, 4 May 2022 18:47:21 +0200 Message-Id: <20220504153128.246294160@linuxfoundation.org> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504153110.096069935@linuxfoundation.org> References: <20220504153110.096069935@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 @@ -2136,18 +2136,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]) @@ -2171,7 +2159,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); @@ -2183,18 +2170,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; @@ -2210,6 +2185,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); @@ -2229,12 +2213,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) @@ -2255,6 +2247,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; @@ -2284,6 +2277,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; }