From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793831326; b=FIyDoxPeTCb2ZbuBoeJhUl1Y/2YjpNtIrg5TEbTdHwk2MolMbBmUlpf9aiKR7af2aBwP 3StG0grAL2k/IUtUmpgs+nL7/xK13fqH1t9FbKJnF/gSonHlX4gQG8eKWg7ui3G+bNrl6 QJIhEer4C9cu4Du3YU9nzS8vrojjVb+6lJBu1a4idsc7TRvf5gzf5bWL5JKfniXNlUJCQ h4JoK5zxZ4Dj9oWD9CGuLi1vXI3BYSKCfL4QKMsq27oc/ndLFCMh0fe4Ci0KDeFnT3aso xH0Pjik8zIr9eEGNT3WeLHhiMH43lB9uw6BYIqIuujMsQzwJ6aHz6zjAT+TzKNJMXrQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793831326; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=1jUGWuiAiaOE3Ys+6bGHGOWs0rxOeD+kJInZDE0+zuc=; b=RqAYD5H88D30Qf6rDkLQKN5vJ8W15lSKtBDefsxbDl+fnuhqlgtYmBjkLXKCOTEMX8Sz qkaEK8D+ik8Q5R2qCKw4h2koyfYrPiw9plaI1xdjMQK/CIjHybJE6K8z6Kc5tdTPgyPm6 fMF0txflYeE/nbNIPVGZLMVhszKM9AtXhw+DSdolFM1PBuozF79pds6FLaEqahBu08HG9 DDhR4VCOqL1/AdoZ1dWblx4pxQWI0WuBNpEh8UXJS+JmaBPmhMcAhkBgRMDYfnp4bUPdh MPvKmL+X1VzQ0VBLHPA+S3OKnMK/vNtnu1zgjQEORHWdrF1mDB9iaQhI8lG988gBlFw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=KGgcDE4P; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2C86606A33A; Wed, 4 Nov 2026 22:28:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=KGgcDE4P Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D4101F000C1; Wed, 4 Nov 2026 22:28:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1793831325; bh=1jUGWuiAiaOE3Ys+6bGHGOWs0rxOeD+kJInZDE0+zuc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KGgcDE4Par4GNQ06LgxtoURGZ1qljLPpnhRRihRHzsZ85ZK1UchI0EIhPqmaRDU84 OACB6McKHNrPEkrsgsxjOXgIfdF9Mna3iEj7Mx1ZwgEJ7IcrGYmzGonavFbvQS0yyF 5/xg/M1vLculmS1pobDVhDOph76WiTf3WBZmHS5c= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Johan Hovold , Sasha Levin , stable@kernel.org Subject: [PATCH 6.18 0597/1005] serial: fix ioctl hangup race Date: Wed, 4 Nov 2026 16:05:30 -0500 Message-ID: <20261104211100.580241861@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261104211043.516122098@linuxfoundation.org> References: <20261104211043.516122098@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Johan Hovold [ Upstream commit 8ca59f7baee7c72cf7729950b4ab2e7f910c9549 ] The tty ioctls can race with hangup and end up calling into a tty driver for a device that is already gone or powered down. Add the missing checks to make sure the port has not been hung up before accessing the hardware to avoid issues like kernel panic due to unclocked accesses. Note that TIOCGSERIAL, TIOCGICOUNT do not access hardware and are therefore not affected by the race. Also note that the initialised check in uart_set_ldisc() added by commit 2f70e49ed860 ("serial_core: Check for port state when tty is in error state") should have been done under the port lock to avoid racing with uart_do_autoconfig(). Fixes: 04f378b198da ("tty: BKL pushdown") Cc: stable@kernel.org # 2.6.26 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260910130816.642699-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/tty/serial/serial_core.c | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 5b6d4d67beabe..94da7977f6774 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -899,7 +899,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, upf_t old_flags, new_flags; int retval; - if (!uport) + if (!uport || tty_io_error(tty)) return -EIO; new_port = new_info->port; @@ -1126,7 +1126,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) guard(mutex)(&port->mutex); uport = uart_port_check(state); - if (!uport) + if (!uport || tty_io_error(tty)) return -EIO; if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl) @@ -1151,7 +1151,7 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) */ scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &port->mutex) { uport = uart_port_check(state); - if (!uport) + if (!uport || tty_io_error(tty)) return -EIO; if (tty_port_users(port) != 1) @@ -1206,7 +1206,7 @@ static void uart_enable_ms(struct uart_port *uport) * FIXME: This wants extracting into a common all driver implementation * of TIOCMWAIT using tty_port. */ -static int uart_wait_modem_status(struct uart_state *state, unsigned long arg) +static int uart_wait_modem_status(struct tty_struct *tty, struct uart_state *state, unsigned long arg) { struct uart_port *uport; struct tty_port *port = &state->port; @@ -1220,11 +1220,21 @@ static int uart_wait_modem_status(struct uart_state *state, unsigned long arg) uport = uart_port_ref(state); if (!uport) return -EIO; + + mutex_lock(&port->mutex); + if (tty_io_error(tty)) { + mutex_unlock(&port->mutex); + ret = -EIO; + goto out_deref; + } + uart_port_lock_irq(uport); memcpy(&cprev, &uport->icount, sizeof(struct uart_icount)); uart_enable_ms(uport); uart_port_unlock_irq(uport); + mutex_unlock(&port->mutex); + add_wait_queue(&port->delta_msr_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -1253,6 +1263,7 @@ static int uart_wait_modem_status(struct uart_state *state, unsigned long arg) } __set_current_state(TASK_RUNNING); remove_wait_queue(&port->delta_msr_wait, &wait); +out_deref: uart_port_deref(uport); return ret; @@ -1577,7 +1588,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) /* This should only be used when the hardware is present. */ if (cmd == TIOCMIWAIT) - return uart_wait_modem_status(state, arg); + return uart_wait_modem_status(tty, state, arg); /* rs485_config requires more locking than others */ if (cmd == TIOCSRS485) @@ -1633,14 +1644,13 @@ static void uart_set_ldisc(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct uart_port *uport; - struct tty_port *port = &state->port; - - if (!tty_port_initialized(port)) - return; mutex_lock(&state->port.mutex); uport = uart_port_check(state); - if (uport && uport->ops->set_ldisc) + if (!uport || tty_io_error(tty)) + return; + + if (uport->ops->set_ldisc) uport->ops->set_ldisc(uport, &tty->termios); mutex_unlock(&state->port.mutex); } @@ -1657,7 +1667,7 @@ static void uart_set_termios(struct tty_struct *tty, guard(mutex)(&state->port.mutex); uport = uart_port_check(state); - if (!uport) + if (!uport || tty_io_error(tty)) return; /* @@ -1810,7 +1820,14 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) * 'timeout' / 'expire' give us the maximum amount of time * we wait. */ - while (!port->ops->tx_empty(port)) { + for (;;) { + mutex_lock(&state->port.mutex); + if (tty_io_error(tty) || port->ops->tx_empty(port)) { + mutex_unlock(&state->port.mutex); + break; + } + mutex_unlock(&state->port.mutex); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; -- 2.53.0