[PATCH] USB: fix bug in visor driver with throttle/unthrottle causing oopses.

Thanks to Mark Lord <mlord@pobox.com> for reporting this and helping with testing.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Chris Wright <chrisw@osdl.org>
This commit is contained in:
gregkh@suse.de 2005-03-23 15:26:40 -08:00 committed by
parent d49a9ad0b5
commit 77068954f8
1 changed files with 27 additions and 11 deletions

View File

@ -386,6 +386,7 @@ struct visor_private {
int bytes_in;
int bytes_out;
int outstanding_urbs;
int throttled;
};
/* number of outstanding urbs to prevent userspace DoS from happening */
@ -415,6 +416,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
priv->bytes_in = 0;
priv->bytes_out = 0;
priv->outstanding_urbs = 0;
priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
/*
@ -602,6 +604,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned long flags;
int i;
int throttled;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@ -627,18 +630,21 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
}
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in += urb->actual_length;
throttled = priv->throttled;
spin_unlock_irqrestore(&priv->lock, flags);
/* Continue trying to always read */
usb_fill_bulk_urb (port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
/* Continue trying to always read if we should */
if (!throttled) {
usb_fill_bulk_urb (port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
return;
}
@ -683,16 +689,26 @@ exit:
static void visor_throttle (struct usb_serial_port *port)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
usb_kill_urb(port->read_urb);
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = 1;
spin_unlock_irqrestore(&priv->lock, flags);
}
static void visor_unthrottle (struct usb_serial_port *port)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);