| From stable-bounces@linux.kernel.org Mon Feb 5 06:57:55 2007 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Mon, 5 Feb 2007 09:56:15 -0500 (EST) |
| Subject: USB: fix concurrent buffer access in the hub driver |
| To: Greg KH <greg@kroah.com> |
| Cc: stable@kernel.org, USB development list <linux-usb-devel@lists.sourceforge.net>, Adrian Bunk <bunk@stusta.de> |
| Message-ID: <Pine.LNX.4.44L0.0702050950390.3533-100000@iolanthe.rowland.org> |
| |
| |
| 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 | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- linux-2.6.20.1.orig/drivers/usb/core/hub.c |
| +++ linux-2.6.20.1/drivers/usb/core/hub.c |
| @@ -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 |
| { |
| 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 |
| *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 |
| 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_hu |
| { |
| 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_hu |
| *change = le16_to_cpu(hub->status->port.wPortChange); |
| ret = 0; |
| } |
| + mutex_unlock(&hub->status_mutex); |
| return ret; |
| } |
| |