mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
serial: core: fix TIOCSSERIAL and TIOCSERCONFIG on uninitialised ports
Commit8ca59f7bae("serial: fix ioctl hangup race") made uart_set_info() and uart_do_autoconfig() return -EIO when TTY_IO_ERROR is set, so that they do not run on a port that has been hung up. However, TTY_IO_ERROR is also set on a port that could not be started, for example because its type is unknown, and by uart_shutdown(), which both functions call. As of now, setserial cannot configure a port that the kernel did not detect, and an autoconfig that follows a port, irq or type change in the same setserial call fails on any port. The issue can be reproduced with setserial (busybox) on a port without a detected UART, for example ttyS3 of a QEMU guest: setserial /dev/ttyS3 uart 16550A setserial -g /dev/ttyS3 Before commit8ca59f7bae("serial: fix ioctl hangup race"), the result is: /dev/ttyS3, UART: 16550A, Port: 0x02e8, IRQ: 3 After that commit, the result is: setserial: can't set serial info: Input/output error /dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3 This patch will check tty_port_active() in these two functions instead. uart_hangup() clears it under the port mutex, and it stays set on an open port that could not be started. Fixes:8ca59f7bae("serial: fix ioctl hangup race") Cc: stable@kernel.org Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu> Tested-by: Johan Hovold <johan@kernel.org> Reviewed-by: Johan Hovold <johan@kernel.org> Link: https://patch.msgid.link/20261010034616.3915864-1-hengyul@cs.unc.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ae588038e3
commit
e1f46a09df
|
|
@ -895,7 +895,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
|||
upf_t old_flags, new_flags;
|
||||
int retval;
|
||||
|
||||
if (!uport || tty_io_error(tty))
|
||||
/*
|
||||
* TTY_IO_ERROR is also set on a port that could not be started, and
|
||||
* this is how such a port is configured. Only refuse a hung up port.
|
||||
*/
|
||||
if (!uport || !tty_port_active(port))
|
||||
return -EIO;
|
||||
|
||||
new_port = new_info->port;
|
||||
|
|
@ -1143,7 +1147,8 @@ 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 || tty_io_error(tty))
|
||||
/* As in uart_set_info(), only refuse a hung up port. */
|
||||
if (!uport || !tty_port_active(port))
|
||||
return -EIO;
|
||||
|
||||
if (tty_port_users(port) != 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user