From 51ad36baacb3b2fd1bd980138a937d30d6c84cdf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 6 Jun 2022 13:04:21 +0300 Subject: [PATCH] serial: return -EINVAL for non-legacy RS485 flags MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In order to be add new flags more cleanly and safely, return -EINVAL from TIOCSRS485 ioctl for the flags bits which are not among the current legacy ones. This might cause a regression for userspace as those non-flag bits do not currently trigger -EINVAL. However, it would only occur if the userspace is sending garbage bits so perhaps we'll get away with this change. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-25-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 6be5387205648..621fc15e2e549 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1276,6 +1276,27 @@ static int uart_get_icount(struct tty_struct *tty, return 0; } +#define SER_RS485_LEGACY_FLAGS (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | \ + SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX | \ + SER_RS485_TERMINATE_BUS) + +static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *rs485) +{ + u32 flags = rs485->flags; + + /* Don't return -EINVAL for unsupported legacy flags */ + flags &= ~SER_RS485_LEGACY_FLAGS; + + /* + * For any bit outside of the legacy ones that is not supported by + * the driver, return -EINVAL. + */ + if (flags & ~port->rs485_supported->flags) + return -EINVAL; + + return 0; +} + static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) { u32 supported_flags = port->rs485_supported->flags; @@ -1375,6 +1396,9 @@ static int uart_set_rs485_config(struct uart_port *port, if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user))) return -EFAULT; + ret = uart_check_rs485_flags(port, &rs485); + if (ret) + return ret; uart_sanitize_serial_rs485(port, &rs485); spin_lock_irqsave(&port->lock, flags); -- 2.30.2