serial: core: fix sanitizing check for RTS settings
authorLino Sanfilippo <l.sanfilippo@kunbus.com>
Wed, 3 Jan 2024 06:18:14 +0000 (07:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jan 2024 23:35:43 +0000 (15:35 -0800)
commit 4afeced55baa391490b61ed9164867e2927353ed upstream.

Among other things uart_sanitize_serial_rs485() tests the sanity of the RTS
settings in a RS485 configuration that has been passed by userspace.
If RTS-on-send and RTS-after-send are both set or unset the configuration
is adjusted and RTS-after-send is disabled and RTS-on-send enabled.

This however makes only sense if both RTS modes are actually supported by
the driver.

With commit be2e2cb1d281 ("serial: Sanitize rs485_struct") the code does
take the driver support into account but only checks if one of both RTS
modes are supported. This may lead to the errorneous result of RTS-on-send
being set even if only RTS-after-send is supported.

Fix this by changing the implemented logic: First clear all unsupported
flags in the RS485 configuration, then adjust an invalid RTS setting by
taking into account which RTS mode is supported.

Cc: <stable@vger.kernel.org>
Fixes: be2e2cb1d281 ("serial: Sanitize rs485_struct")
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
Link: https://lore.kernel.org/r/20240103061818.564-4-l.sanfilippo@kunbus.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/serial_core.c

index f912f8b..e56d34d 100644 (file)
@@ -1370,19 +1370,27 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4
                return;
        }
 
+       rs485->flags &= supported_flags;
+
        /* Pick sane settings if the user hasn't */
-       if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) &&
-           !(rs485->flags & SER_RS485_RTS_ON_SEND) ==
+       if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
            !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
-               dev_warn_ratelimited(port->dev,
-                       "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n",
-                       port->name, port->line);
-               rs485->flags |= SER_RS485_RTS_ON_SEND;
-               rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
-               supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND;
-       }
+               if (supported_flags & SER_RS485_RTS_ON_SEND) {
+                       rs485->flags |= SER_RS485_RTS_ON_SEND;
+                       rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
 
-       rs485->flags &= supported_flags;
+                       dev_warn_ratelimited(port->dev,
+                               "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n",
+                               port->name, port->line);
+               } else {
+                       rs485->flags |= SER_RS485_RTS_AFTER_SEND;
+                       rs485->flags &= ~SER_RS485_RTS_ON_SEND;
+
+                       dev_warn_ratelimited(port->dev,
+                               "%s (%d): invalid RTS setting, using RTS_AFTER_SEND instead\n",
+                               port->name, port->line);
+               }
+       }
 
        uart_sanitize_serial_rs485_delays(port, rs485);