]> git.baikalelectronics.ru Git - kernel.git/commitdiff
serial: return -EINVAL for non-legacy RS485 flags
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 6 Jun 2022 10:04:21 +0000 (13:04 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Jun 2022 11:49:57 +0000 (13:49 +0200)
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>
drivers/tty/serial/serial_core.c

index 6be5387205648a251fa85ff9363a40beb68cc998..621fc15e2e54992abc052f3d9e14fdb8c155cb60 100644 (file)
@@ -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);