Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62127a58 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

USB: fix race in ftdio_write



this has the same race as the visor driver. The counter must be incremented
under the lock it is checked under.

Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b80349b1
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -1433,6 +1433,7 @@ static int ftdi_write (struct usb_serial_port *port,
		dbg("%s - write limit hit\n", __FUNCTION__);
		return 0;
	}
	priv->tx_outstanding_urbs++;
	spin_unlock_irqrestore(&priv->tx_lock, flags);

	data_offset = priv->write_offset;
@@ -1450,14 +1451,15 @@ static int ftdi_write (struct usb_serial_port *port,
	buffer = kmalloc (transfer_size, GFP_ATOMIC);
	if (!buffer) {
		err("%s ran out of kernel memory for urb ...", __FUNCTION__);
		return -ENOMEM;
		count = -ENOMEM;
		goto error_no_buffer;
	}

	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		err("%s - no more free urbs", __FUNCTION__);
		kfree (buffer);
		return -ENOMEM;
		count = -ENOMEM;
		goto error_no_urb;
	}

	/* Copy data */
@@ -1499,10 +1501,9 @@ static int ftdi_write (struct usb_serial_port *port,
	if (status) {
		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
		count = status;
		kfree (buffer);
		goto error;
	} else {
		spin_lock_irqsave(&priv->tx_lock, flags);
		++priv->tx_outstanding_urbs;
		priv->tx_outstanding_bytes += count;
		priv->tx_bytes += count;
		spin_unlock_irqrestore(&priv->tx_lock, flags);
@@ -1514,6 +1515,15 @@ static int ftdi_write (struct usb_serial_port *port,

	dbg("%s write returning: %d", __FUNCTION__, count);
	return count;
error:
	usb_free_urb(urb);
error_no_urb:
	kfree (buffer);
error_no_buffer:
	spin_lock_irqsave(&priv->tx_lock, flags);
	priv->tx_outstanding_urbs--;
	spin_unlock_irqrestore(&priv->tx_lock, flags);
	return count;
} /* ftdi_write */