diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-02-05 09:56:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-16 18:32:19 -0500 |
commit | db90e7a15cb4a160610b4e58576f25539ca216e7 (patch) | |
tree | 10e0a54e3e20a42a8dd4b20448705f0ebad1dd94 /drivers/usb | |
parent | af59cf404fc7ad6cc642de9e78252fb264917611 (diff) |
USB: fix concurrent buffer access in the hub driver
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7d6006573543..50c0db15304a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -44,6 +44,7 @@ struct usb_hub { | |||
44 | struct usb_hub_status hub; | 44 | struct usb_hub_status hub; |
45 | struct usb_port_status port; | 45 | struct usb_port_status port; |
46 | } *status; /* buffer for status reports */ | 46 | } *status; /* buffer for status reports */ |
47 | struct mutex status_mutex; /* for the status buffer */ | ||
47 | 48 | ||
48 | int error; /* last reported error */ | 49 | int error; /* last reported error */ |
49 | int nerrors; /* track consecutive errors */ | 50 | int nerrors; /* track consecutive errors */ |
@@ -535,6 +536,7 @@ static int hub_hub_status(struct usb_hub *hub, | |||
535 | { | 536 | { |
536 | int ret; | 537 | int ret; |
537 | 538 | ||
539 | mutex_lock(&hub->status_mutex); | ||
538 | ret = get_hub_status(hub->hdev, &hub->status->hub); | 540 | ret = get_hub_status(hub->hdev, &hub->status->hub); |
539 | if (ret < 0) | 541 | if (ret < 0) |
540 | dev_err (hub->intfdev, | 542 | dev_err (hub->intfdev, |
@@ -544,6 +546,7 @@ static int hub_hub_status(struct usb_hub *hub, | |||
544 | *change = le16_to_cpu(hub->status->hub.wHubChange); | 546 | *change = le16_to_cpu(hub->status->hub.wHubChange); |
545 | ret = 0; | 547 | ret = 0; |
546 | } | 548 | } |
549 | mutex_unlock(&hub->status_mutex); | ||
547 | return ret; | 550 | return ret; |
548 | } | 551 | } |
549 | 552 | ||
@@ -617,6 +620,7 @@ static int hub_configure(struct usb_hub *hub, | |||
617 | ret = -ENOMEM; | 620 | ret = -ENOMEM; |
618 | goto fail; | 621 | goto fail; |
619 | } | 622 | } |
623 | mutex_init(&hub->status_mutex); | ||
620 | 624 | ||
621 | hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); | 625 | hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); |
622 | if (!hub->descriptor) { | 626 | if (!hub->descriptor) { |
@@ -1396,6 +1400,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, | |||
1396 | { | 1400 | { |
1397 | int ret; | 1401 | int ret; |
1398 | 1402 | ||
1403 | mutex_lock(&hub->status_mutex); | ||
1399 | ret = get_port_status(hub->hdev, port1, &hub->status->port); | 1404 | ret = get_port_status(hub->hdev, port1, &hub->status->port); |
1400 | if (ret < 4) { | 1405 | if (ret < 4) { |
1401 | dev_err (hub->intfdev, | 1406 | dev_err (hub->intfdev, |
@@ -1407,6 +1412,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, | |||
1407 | *change = le16_to_cpu(hub->status->port.wPortChange); | 1412 | *change = le16_to_cpu(hub->status->port.wPortChange); |
1408 | ret = 0; | 1413 | ret = 0; |
1409 | } | 1414 | } |
1415 | mutex_unlock(&hub->status_mutex); | ||
1410 | return ret; | 1416 | return ret; |
1411 | } | 1417 | } |
1412 | 1418 | ||