]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
USB: fix concurrent buffer access in the hub driver
authorAlan Stern <stern@rowland.harvard.edu>
Mon, 5 Feb 2007 14:56:15 +0000 (09:56 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 9 Mar 2007 18:50:19 +0000 (10:50 -0800)
This patch (as849) fixes a bug in the USB hub driver.  A single
pre-allocated buffer is used for all port status reads, but nothing
guarantees exclusive use of the buffer.  A mutex is added to provide
this guarantee.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hub.c

index 1988224b362bf417f2618a8bcb1e448d32f87eee..8ddeed37daec5eee041af354169d71ea2cb9bcf6 100644 (file)
@@ -44,6 +44,7 @@ struct usb_hub {
                struct usb_hub_status   hub;
                struct usb_port_status  port;
        }                       *status;        /* buffer for status reports */
+       struct mutex            status_mutex;   /* for the status buffer */
 
        int                     error;          /* last reported error */
        int                     nerrors;        /* track consecutive errors */
@@ -538,6 +539,7 @@ static int hub_hub_status(struct usb_hub *hub,
 {
        int ret;
 
+       mutex_lock(&hub->status_mutex);
        ret = get_hub_status(hub->hdev, &hub->status->hub);
        if (ret < 0)
                dev_err (hub->intfdev,
@@ -547,6 +549,7 @@ static int hub_hub_status(struct usb_hub *hub,
                *change = le16_to_cpu(hub->status->hub.wHubChange); 
                ret = 0;
        }
+       mutex_unlock(&hub->status_mutex);
        return ret;
 }
 
@@ -620,6 +623,7 @@ static int hub_configure(struct usb_hub *hub,
                ret = -ENOMEM;
                goto fail;
        }
+       mutex_init(&hub->status_mutex);
 
        hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
        if (!hub->descriptor) {
@@ -1418,6 +1422,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
 {
        int ret;
 
+       mutex_lock(&hub->status_mutex);
        ret = get_port_status(hub->hdev, port1, &hub->status->port);
        if (ret < 4) {
                dev_err (hub->intfdev,
@@ -1429,6 +1434,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
                *change = le16_to_cpu(hub->status->port.wPortChange); 
                ret = 0;
        }
+       mutex_unlock(&hub->status_mutex);
        return ret;
 }