patch "USB: cdc-acm: fix rounding error in TIOCSSERIAL" added to usb-linus
Subsystems (3)
This is a note to let you know that I've just added the patch titled
USB: cdc-acm: fix rounding error in TIOCSSERIAL
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From b401f8c4f492cbf74f3f59c9141e5be3071071bb Mon Sep 17 00:00:00 2001
From: Anthony Mallet <[email protected]>
Date: Thu, 12 Mar 2020 14:31:01 +0100
Subject: USB: cdc-acm: fix rounding error in TIOCSSERIAL
By default, tty_port_init() initializes those parameters to a multiple of HZ. For instance in line 69 of tty_port.c:
port->close_delay = (50 * HZ) / 100;
https://github.com/torvalds/linux/blob/master/drivers/tty/tty_port.c#L69
With e.g. CONFIG_HZ = 250 (as this is the case for Ubuntu 18.04 linux-image-4.15.0-37-generic), the default setting for close_delay is thus 125.
When ioctl(fd, TIOCGSERIAL, &s) is executed, the setting returned in user space is '12' (125/10). When ioctl(fd, TIOCSSERIAL, &s) is then executed with the same setting '12', the value is interpreted as '120' which is different from the current setting and a EPERM error may be raised by set_serial_info() if !CAP_SYS_ADMIN.
https://github.com/torvalds/linux/blob/master/drivers/usb/class/cdc-acm.c#L919
--- drivers/usb/class/cdc-acm.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/usb/class/cdc-acm.c +16 -9
@@ -907,6 +907,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) {struct acm *acm = tty->driver_data;unsigned int closing_wait, close_delay; +unsigned int old_closing_wait, old_close_delay;int retval =0 ; close_delay =msecs_to_jiffies (ss->close_delay *10 );
@@ -914,18 +915,24 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) ASYNC_CLOSING_WAIT_NONE :msecs_to_jiffies (ss->closing_wait *10 ); +/* we must redo the rounding here, so that the values match */ + old_close_delay =jiffies_to_msecs (acm->port.close_delay) /10 ; + old_closing_wait = acm->port.closing_wait ==ASYNC_CLOSING_WAIT_NONE ? +ASYNC_CLOSING_WAIT_NONE : +jiffies_to_msecs (acm->port.closing_wait) /10 ; +mutex_lock (&acm->port.mutex); -if (!capable (CAP_SYS_ADMIN )) { -if ((close_delay != acm->port.close_delay) || - (closing_wait != acm->port.closing_wait)) +if ((ss->close_delay != old_close_delay) || + (ss->closing_wait != old_closing_wait)) { +if (!capable (CAP_SYS_ADMIN )) retval = -EPERM ; -else - retval = -EOPNOTSUPP ; - }else { - acm->port.close_delay = close_delay; - acm->port.closing_wait = closing_wait; - } +else { + acm->port.close_delay = close_delay; + acm->port.closing_wait = closing_wait; + } + }else + retval = -EOPNOTSUPP ;mutex_unlock (&acm->port.mutex);return retval;
Signature · 1 line
2.25.1