|
Oliver Neukum |
2c91d7 |
From b401f8c4f492cbf74f3f59c9141e5be3071071bb Mon Sep 17 00:00:00 2001
|
|
Oliver Neukum |
2c91d7 |
From: Anthony Mallet <anthony.mallet@laas.fr>
|
|
Oliver Neukum |
2c91d7 |
Date: Thu, 12 Mar 2020 14:31:01 +0100
|
|
Oliver Neukum |
2c91d7 |
Subject: [PATCH] USB: cdc-acm: fix rounding error in TIOCSSERIAL
|
|
Oliver Neukum |
2c91d7 |
Git-commit: b401f8c4f492cbf74f3f59c9141e5be3071071bb
|
|
Oliver Neukum |
2c91d7 |
References: git-fixes
|
|
Oliver Neukum |
2c91d7 |
Patch-mainline: v5.6-rc7
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
By default, tty_port_init() initializes those parameters to a multiple
|
|
Oliver Neukum |
2c91d7 |
of HZ. For instance in line 69 of tty_port.c:
|
|
Oliver Neukum |
2c91d7 |
port->close_delay = (50 * HZ) / 100;
|
|
Oliver Neukum |
2c91d7 |
https://github.com/torvalds/linux/blob/master/drivers/tty/tty_port.c#L69
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
With e.g. CONFIG_HZ = 250 (as this is the case for Ubuntu 18.04
|
|
Oliver Neukum |
2c91d7 |
linux-image-4.15.0-37-generic), the default setting for close_delay is
|
|
Oliver Neukum |
2c91d7 |
thus 125.
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
When ioctl(fd, TIOCGSERIAL, &s) is executed, the setting returned in
|
|
Oliver Neukum |
2c91d7 |
user space is '12' (125/10). When ioctl(fd, TIOCSSERIAL, &s) is then
|
|
Oliver Neukum |
2c91d7 |
executed with the same setting '12', the value is interpreted as '120'
|
|
Oliver Neukum |
2c91d7 |
which is different from the current setting and a EPERM error may be
|
|
Oliver Neukum |
2c91d7 |
raised by set_serial_info() if !CAP_SYS_ADMIN.
|
|
Oliver Neukum |
2c91d7 |
https://github.com/torvalds/linux/blob/master/drivers/usb/class/cdc-acm.c#L919
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
Fixes: ba2d8ce9db0a6 ("cdc-acm: implement TIOCSSERIAL to avoid blocking close(2)")
|
|
Oliver Neukum |
2c91d7 |
Signed-off-by: Anthony Mallet <anthony.mallet@laas.fr>
|
|
Oliver Neukum |
2c91d7 |
Cc: stable <stable@vger.kernel.org>
|
|
Oliver Neukum |
2c91d7 |
Link: https://lore.kernel.org/r/20200312133101.7096-2-anthony.mallet@laas.fr
|
|
Oliver Neukum |
2c91d7 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Oliver Neukum |
2c91d7 |
Signed-off-by: Oliver Neukum <oneukum@suse.com>
|
|
Oliver Neukum |
2c91d7 |
---
|
|
Oliver Neukum |
2c91d7 |
drivers/usb/class/cdc-acm.c | 25 ++++++++++++++++---------
|
|
Oliver Neukum |
2c91d7 |
1 file changed, 16 insertions(+), 9 deletions(-)
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
--- a/drivers/usb/class/cdc-acm.c
|
|
Oliver Neukum |
2c91d7 |
+++ b/drivers/usb/class/cdc-acm.c
|
|
Oliver Neukum |
2c91d7 |
@@ -942,6 +942,7 @@ static int set_serial_info(struct acm *a
|
|
Oliver Neukum |
2c91d7 |
{
|
|
Oliver Neukum |
2c91d7 |
struct serial_struct new_serial;
|
|
Oliver Neukum |
2c91d7 |
unsigned int closing_wait, close_delay;
|
|
Oliver Neukum |
2c91d7 |
+ unsigned int old_closing_wait, old_close_delay;
|
|
Oliver Neukum |
2c91d7 |
int retval = 0;
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
|
|
Oliver Neukum |
2c91d7 |
@@ -951,18 +952,24 @@ static int set_serial_info(struct acm *a
|
|
Oliver Neukum |
2c91d7 |
closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
|
Oliver Neukum |
2c91d7 |
ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
+ /* we must redo the rounding here, so that the values match */
|
|
Oliver Neukum |
2c91d7 |
+ old_close_delay = jiffies_to_msecs(acm->port.close_delay) / 10;
|
|
Oliver Neukum |
2c91d7 |
+ old_closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
|
Oliver Neukum |
2c91d7 |
+ ASYNC_CLOSING_WAIT_NONE :
|
|
Oliver Neukum |
2c91d7 |
+ jiffies_to_msecs(acm->port.closing_wait) / 10;
|
|
Oliver Neukum |
2c91d7 |
+
|
|
Oliver Neukum |
2c91d7 |
mutex_lock(&acm->port.mutex);
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
- if (!capable(CAP_SYS_ADMIN)) {
|
|
Oliver Neukum |
2c91d7 |
- if ((close_delay != acm->port.close_delay) ||
|
|
Oliver Neukum |
2c91d7 |
- (closing_wait != acm->port.closing_wait))
|
|
Oliver Neukum |
2c91d7 |
+ if ((new_serial.close_delay != old_close_delay) ||
|
|
Oliver Neukum |
2c91d7 |
+ (new_serial.closing_wait != old_closing_wait)) {
|
|
Oliver Neukum |
2c91d7 |
+ if (!capable(CAP_SYS_ADMIN))
|
|
Oliver Neukum |
2c91d7 |
retval = -EPERM;
|
|
Oliver Neukum |
2c91d7 |
- else
|
|
Oliver Neukum |
2c91d7 |
- retval = -EOPNOTSUPP;
|
|
Oliver Neukum |
2c91d7 |
- } else {
|
|
Oliver Neukum |
2c91d7 |
- acm->port.close_delay = close_delay;
|
|
Oliver Neukum |
2c91d7 |
- acm->port.closing_wait = closing_wait;
|
|
Oliver Neukum |
2c91d7 |
- }
|
|
Oliver Neukum |
2c91d7 |
+ else {
|
|
Oliver Neukum |
2c91d7 |
+ acm->port.close_delay = close_delay;
|
|
Oliver Neukum |
2c91d7 |
+ acm->port.closing_wait = closing_wait;
|
|
Oliver Neukum |
2c91d7 |
+ }
|
|
Oliver Neukum |
2c91d7 |
+ } else
|
|
Oliver Neukum |
2c91d7 |
+ retval = -EOPNOTSUPP;
|
|
Oliver Neukum |
2c91d7 |
|
|
Oliver Neukum |
2c91d7 |
mutex_unlock(&acm->port.mutex);
|
|
Oliver Neukum |
2c91d7 |
return retval;
|