aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2022-06-06 13:04:21 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-06-10 13:49:57 +0200
commit51ad36baacb3b2fd1bd980138a937d30d6c84cdf (patch)
tree8eabb46704586aeb0f9d9855fb0f2171289b170d
parentserial: Clear rs485 struct when non-RS485 mode is set (diff)
downloadlinux-rng-51ad36baacb3b2fd1bd980138a937d30d6c84cdf.tar.xz
linux-rng-51ad36baacb3b2fd1bd980138a937d30d6c84cdf.zip
serial: return -EINVAL for non-legacy RS485 flags
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 <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/20220606100433.13793-25-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/serial_core.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 6be538720564..621fc15e2e54 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);