USB serial fixes for 7.2-rc2

Here is a fix for an information leak in the keyspan_pda driver and
 three fixes for digi_acceleport addressing stuck rx if a port is closed
 while throttled, a hard lockup on disconnect and write buffer
 corruption.
 
 Included are also some new modem device ids.
 
 All have been in linux-next for a few days with no reported issues.
 -----BEGIN PGP SIGNATURE-----
 
 iJEEABYKADkWIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCakd3IxsUgAAAAAAEAA5t
 YW51MiwyLjUrMS4xMiwyLDIACgkQC8XNwux9ZQhbZAEAwMNsbp0cXHxNt1ork9xu
 dxPabcqTYZ5FwOEGktY7k4oA+we0wwuk/5862uDVzG+hNESL65XIDfuPrtLq7l1C
 4ZoO
 =ZNNY
 -----END PGP SIGNATURE-----

Merge tag 'usb-serial-7.2-rc2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus

Johan writes:

USB serial fixes for 7.2-rc2

Here is a fix for an information leak in the keyspan_pda driver and
three fixes for digi_acceleport addressing stuck rx if a port is closed
while throttled, a hard lockup on disconnect and write buffer
corruption.

Included are also some new modem device ids.

All have been in linux-next for a few days with no reported issues.

* tag 'usb-serial-7.2-rc2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial:
  USB: serial: keyspan_pda: fix information leak
  USB: serial: option: add Telit Cinterion FE990D50 compositions
  USB: serial: digi_acceleport: fix broken rx after throttle
  USB: serial: digi_acceleport: fix hard lockup on disconnect
  USB: serial: digi_acceleport: fix write buffer corruption
This commit is contained in:
Greg Kroah-Hartman 2026-07-03 11:41:05 +02:00
commit 07acd41f72
3 changed files with 50 additions and 11 deletions

View File

@ -392,12 +392,14 @@ static int digi_write_oob_command(struct usb_serial_port *port,
len &= ~3;
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
oob_port->write_urb->transfer_buffer_length = len;
ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
}
if (ret)
break;
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
}
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
if (ret)
@ -427,20 +429,22 @@ static int digi_write_inb_command(struct usb_serial_port *port,
int len;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long expire;
unsigned long flags;
dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n",
priv->dp_port_num, count);
if (timeout)
timeout += jiffies;
else
timeout = ULONG_MAX;
expire = jiffies + timeout;
spin_lock_irqsave(&priv->dp_port_lock, flags);
while (count > 0 && ret == 0) {
while (priv->dp_write_urb_in_use &&
time_before(jiffies, timeout)) {
while (priv->dp_write_urb_in_use) {
if (timeout && time_after(jiffies, expire)) {
ret = -ETIMEDOUT;
break;
}
cond_wait_interruptible_timeout_irqrestore(
&priv->write_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@ -449,6 +453,9 @@ static int digi_write_inb_command(struct usb_serial_port *port,
spin_lock_irqsave(&priv->dp_port_lock, flags);
}
if (ret)
break;
/* len must be a multiple of 4 and small enough to */
/* guarantee the write will send buffered data first, */
/* so commands are in order with data and not split */
@ -1069,6 +1076,7 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios;
int throttled;
/* be sure the device is started up */
if (digi_startup_device(port->serial) != 0)
@ -1096,6 +1104,21 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
not_termios.c_iflag = ~tty->termios.c_iflag;
digi_set_termios(tty, port, &not_termios);
}
spin_lock_irq(&priv->dp_port_lock);
throttled = priv->dp_throttle_restart;
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
spin_unlock_irq(&priv->dp_port_lock);
if (throttled) {
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret) {
dev_err(&port->dev, "failed to submit read urb: %d\n", ret);
return ret;
}
}
return 0;
}

View File

@ -516,7 +516,7 @@ static int keyspan_pda_write_start(struct usb_serial_port *port)
if (count == room)
schedule_work(&priv->unthrottle_work);
return count;
return 0;
}
static void keyspan_pda_write_bulk_callback(struct urb *urb)

View File

@ -1325,6 +1325,22 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x30), /* Telit FE990D50 (RNDIS) */
.driver_info = NCTRL(6) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x60) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x30), /* Telit FE990D50 (rmnet) */
.driver_info = NCTRL(5) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x60) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x30), /* Telit FE990D50 (MBIM) */
.driver_info = NCTRL(6) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x60) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x30), /* Telit FE990D50 (ECM) */
.driver_info = NCTRL(6) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x60) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1031, 0xff), /* Telit LE910C1-EUX */
.driver_info = NCTRL(0) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */