Received: by 2002:a05:6358:4e97:b0:b3:742d:4702 with SMTP id ce23csp3114712rwb; Mon, 15 Aug 2022 18:28:16 -0700 (PDT) X-Google-Smtp-Source: AA6agR7Ly90H148drXi9PhMJcit0KQTA+YFD1yPSLH4hieZbbKT49iCZP5zbDMvSJ3NmbxKaKmdY X-Received: by 2002:a17:90a:fe7:b0:1fa:996d:14b2 with SMTP id 94-20020a17090a0fe700b001fa996d14b2mr177770pjz.7.1660613296220; Mon, 15 Aug 2022 18:28:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1660613296; cv=none; d=google.com; s=arc-20160816; b=JB9iADmQqx0EV7/eDdicGM7BoiSfCkH+2B2t8JasgdZ/ux3Bh1gtVQmdqYPUv3Zca2 EFzW9i8P+N2QrTN0QLnynsImZAVS1O9rD3OSnvW6Ah2lxwTYyVlI9qwdnZ+mTGkA8NAd 7KGpp8xIc8P5BLIZrOyUE5fNAVnvBs4Cjb25lLhzij6f5IStBF4w17Kt1sg31kozPPeX 9qlneKi6w0ukh3HT8I1L46kno48BKNXHhPJejZ8xpxZ4/haEOU0tceM2nRXwU0pK9p0l FNFxu3zknqmcFwLL23u6RrSgH88Zx6u1WDGN4W2x0cBZg8JMo/k6nR7zwOCnyc35hc0L E8AA== 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=Zu/mC7+5O0eS1hFGCPI1qOjYyYbRZPVh8a2UqAGHjSQ=; b=QwWgs8JWjqdhDWWsWR5P/EQAXL+tLh7SejkSI4uGApRab4AXQOqHG52r9ful3xti2c Caj17Gsqr10A9t2BpcmywenzFlCHt+worpL7v6obrLyOwbfuz4ylhCpuPduz6GUEqpfg jd5CwvDVBfC8KKY0/cFVuuK2DJ8o+4GJUkCKVfXxhaqjvJXdl0mL1cK/a+9zaKC+xQWP 4iS/h/TRJhGEeG+ZuaG8iZFcib7ydCPVa/etROW5JxvBsG6TjvRGhxMUrMRpETHaqdTo iwr9viJHODGlWtlXMomDPvsXRcYYYV43bdUD3LFXsVFyGsyW7XtmgmLfiNeobMYo/6cT Wp/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=JYfMqlzK; 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 r83-20020a632b56000000b00419be2b2b2fsi12571262pgr.735.2022.08.15.18.28.05; Mon, 15 Aug 2022 18:28:16 -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=JYfMqlzK; 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 S1345718AbiHPAnI (ORCPT + 99 others); Mon, 15 Aug 2022 20:43:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53520 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349079AbiHPAlV (ORCPT ); Mon, 15 Aug 2022 20:41:21 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B201518EC25; Mon, 15 Aug 2022 13:39:14 -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 ams.source.kernel.org (Postfix) with ESMTPS id CF992B80EA9; Mon, 15 Aug 2022 20:39:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27E26C433C1; Mon, 15 Aug 2022 20:39:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1660595951; bh=ZqnfYDGRdxhnsuWlBwqWsl53LM0H85pNz2+6oKLxjxg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JYfMqlzKyPo+deIv76b0P/MuzoDverWRTkrwOLbwTMWdBKlHSJgQHZ/R8Y5V2Gzow 6a8N+XUNF2fJ+ASRzuhEJU1YaPRS33HMVmm/W3km1e4sTNMS2G5PpKgD5H9WsPWlG6 cLc53QS4pa2UDj9ufYrBe2zWrnCqJNz6NXpedlDY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Starke , Sasha Levin Subject: [PATCH 5.19 0926/1157] tty: n_gsm: fix tty registration before control channel open Date: Mon, 15 Aug 2022 20:04:42 +0200 Message-Id: <20220815180516.508479429@linuxfoundation.org> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220815180439.416659447@linuxfoundation.org> References: <20220815180439.416659447@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.1 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 [ Upstream commit 01aecd917114577c423f07cec0d186ad007d76fc ] The current implementation registers/deregisters the user ttys at mux attach/detach. That means that the user devices are available before any control channel is open. However, user channel initialization requires an open control channel. Furthermore, the user is not informed if the mux restarts due to configuration changes. Put the registration/deregistration procedure into separate function to improve readability. Move registration to mux activation and deregistration to mux cleanup to keep the user devices only open as long as a control channel exists. The user will be informed via the device driver if the mux was reconfigured in a way that required a mux re-activation. This makes it necessary to add T2 initialization to gsmld_open() for the ldisc open code path (not the reconfiguration code path) to avoid deletion of an uninitialized T2 at mux cleanup. Fixes: d50f6dcaf22a ("tty: n_gsm: expose gsmtty device nodes at ldisc open time") Signed-off-by: Daniel Starke Link: https://lore.kernel.org/r/20220701061652.39604-2-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/tty/n_gsm.c | 117 ++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5a0fd35ce1f9..e8c0ce114c07 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -235,6 +235,7 @@ struct gsm_mux { struct gsm_dlci *dlci[NUM_DLCI]; int old_c_iflag; /* termios c_iflag value before attach */ bool constipated; /* Asked by remote to shut up */ + bool has_devices; /* Devices were registered */ spinlock_t tx_lock; unsigned int tx_bytes; /* TX data outstanding */ @@ -463,6 +464,68 @@ static void gsm_hex_dump_bytes(const char *fname, const u8 *data, kfree(prefix); } +/** + * gsm_register_devices - register all tty devices for a given mux index + * + * @driver: the tty driver that describes the tty devices + * @index: the mux number is used to calculate the minor numbers of the + * ttys for this mux and may differ from the position in the + * mux array. + */ +static int gsm_register_devices(struct tty_driver *driver, unsigned int index) +{ + struct device *dev; + int i; + unsigned int base; + + if (!driver || index >= MAX_MUX) + return -EINVAL; + + base = index * NUM_DLCI; /* first minor for this index */ + for (i = 1; i < NUM_DLCI; i++) { + /* Don't register device 0 - this is the control channel + * and not a usable tty interface + */ + dev = tty_register_device(gsm_tty_driver, base + i, NULL); + if (IS_ERR(dev)) { + if (debug & 8) + pr_info("%s failed to register device minor %u", + __func__, base + i); + for (i--; i >= 1; i--) + tty_unregister_device(gsm_tty_driver, base + i); + return PTR_ERR(dev); + } + } + + return 0; +} + +/** + * gsm_unregister_devices - unregister all tty devices for a given mux index + * + * @driver: the tty driver that describes the tty devices + * @index: the mux number is used to calculate the minor numbers of the + * ttys for this mux and may differ from the position in the + * mux array. + */ +static void gsm_unregister_devices(struct tty_driver *driver, + unsigned int index) +{ + int i; + unsigned int base; + + if (!driver || index >= MAX_MUX) + return; + + base = index * NUM_DLCI; /* first minor for this index */ + for (i = 1; i < NUM_DLCI; i++) { + /* Don't unregister device 0 - this is the control + * channel and not a usable tty interface + */ + tty_unregister_device(gsm_tty_driver, base + i); + } +} + /** * gsm_print_packet - display a frame for debug * @hdr: header to print before decode @@ -2204,6 +2267,10 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) del_timer_sync(&gsm->t2_timer); /* Free up any link layer users and finally the control channel */ + if (gsm->has_devices) { + gsm_unregister_devices(gsm_tty_driver, gsm->num); + gsm->has_devices = false; + } for (i = NUM_DLCI - 1; i >= 0; i--) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); @@ -2227,6 +2294,7 @@ 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 ret; timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); init_waitqueue_head(&gsm->event); @@ -2238,9 +2306,14 @@ static int gsm_activate_mux(struct gsm_mux *gsm) else gsm->receive = gsm1_receive; + ret = gsm_register_devices(gsm_tty_driver, gsm->num); + if (ret) + return ret; + dlci = gsm_dlci_alloc(gsm, 0); if (dlci == NULL) return -ENOMEM; + gsm->has_devices = true; gsm->dead = false; /* Tty opens are now permissible */ return 0; } @@ -2500,39 +2573,14 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) * will need moving to an ioctl path. */ -static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) +static void gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) { - unsigned int base; - int ret, i; - gsm->tty = tty_kref_get(tty); /* Turn off tty XON/XOFF handling to handle it explicitly. */ gsm->old_c_iflag = tty->termios.c_iflag; tty->termios.c_iflag &= (IXON | IXOFF); - ret = gsm_activate_mux(gsm); - if (ret != 0) - tty_kref_put(gsm->tty); - else { - /* Don't register device 0 - this is the control channel and not - a usable tty interface */ - base = mux_num_to_base(gsm); /* Base for this MUX */ - for (i = 1; i < NUM_DLCI; i++) { - struct device *dev; - - dev = tty_register_device(gsm_tty_driver, - base + i, NULL); - if (IS_ERR(dev)) { - for (i--; i >= 1; i--) - tty_unregister_device(gsm_tty_driver, - base + i); - return PTR_ERR(dev); - } - } - } - return ret; } - /** * gsmld_detach_gsm - stop doing 0710 mux * @tty: tty attached to the mux @@ -2543,12 +2591,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) { - unsigned int base = mux_num_to_base(gsm); /* Base for this MUX */ - int i; - WARN_ON(tty != gsm->tty); - for (i = 1; i < NUM_DLCI; i++) - tty_unregister_device(gsm_tty_driver, base + i); /* Restore tty XON/XOFF handling. */ gsm->tty->termios.c_iflag = gsm->old_c_iflag; tty_kref_put(gsm->tty); @@ -2640,7 +2683,6 @@ static void gsmld_close(struct tty_struct *tty) static int gsmld_open(struct tty_struct *tty) { struct gsm_mux *gsm; - int ret; if (tty->ops->write == NULL) return -EINVAL; @@ -2656,12 +2698,11 @@ static int gsmld_open(struct tty_struct *tty) /* Attach the initial passive connection */ gsm->encoding = 1; - ret = gsmld_attach_gsm(tty, gsm); - if (ret != 0) { - gsm_cleanup_mux(gsm, false); - mux_put(gsm); - } - return ret; + gsmld_attach_gsm(tty, gsm); + + timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); + + return 0; } /** -- 2.35.1