]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From 9778c14b4ca2c81e437fc2fd2b1f3d676937db27 Mon Sep 17 00:00:00 2001 |
2 | From: Taku Izumi <izumi.taku@jp.fujitsu.com> | |
3 | Date: Fri, 17 Oct 2008 13:48:36 +0900 | |
4 | Subject: ACPI/PCI: Fix possible race condition on _OSC evaluation | |
5 | Patch-mainline: 2.6.28 | |
6 | References: bnc#438941 | |
7 | ||
8 | Fix possible race condition on _OSC evaluation. | |
9 | ||
10 | Current _OSC evaluation code has possible race condition because it | |
11 | maniputes osc_data linked list or its contents without any lock | |
12 | mechanism. | |
13 | ||
14 | Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | |
15 | Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> | |
16 | Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> | |
17 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
18 | ||
19 | --- | |
20 | drivers/pci/pci-acpi.c | 28 ++++++++++++++++++++-------- | |
21 | 1 file changed, 20 insertions(+), 8 deletions(-) | |
22 | ||
23 | --- a/drivers/pci/pci-acpi.c | |
24 | +++ b/drivers/pci/pci-acpi.c | |
25 | @@ -35,6 +35,8 @@ struct acpi_osc_args { | |
26 | u32 query_result; | |
27 | }; | |
28 | ||
29 | +static DEFINE_MUTEX(pci_acpi_lock); | |
30 | + | |
31 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | |
32 | { | |
33 | struct acpi_osc_data *data; | |
34 | @@ -131,10 +133,12 @@ static acpi_status acpi_query_osc(acpi_h | |
35 | if (ACPI_FAILURE(status)) | |
36 | return status; | |
37 | ||
38 | + mutex_lock(&pci_acpi_lock); | |
39 | osc_data = acpi_get_osc_data(handle); | |
40 | if (!osc_data) { | |
41 | printk(KERN_ERR "acpi osc data array is full\n"); | |
42 | - return AE_ERROR; | |
43 | + status = AE_ERROR; | |
44 | + goto out; | |
45 | } | |
46 | ||
47 | /* do _OSC query for all possible controls */ | |
48 | @@ -149,7 +153,8 @@ static acpi_status acpi_query_osc(acpi_h | |
49 | osc_data->query_result = osc_args.query_result; | |
50 | osc_data->is_queried = 1; | |
51 | } | |
52 | - | |
53 | +out: | |
54 | + mutex_unlock(&pci_acpi_lock); | |
55 | return status; | |
56 | } | |
57 | ||
58 | @@ -190,19 +195,25 @@ acpi_status pci_osc_control_set(acpi_han | |
59 | if (ACPI_FAILURE(status)) | |
60 | return status; | |
61 | ||
62 | + mutex_lock(&pci_acpi_lock); | |
63 | osc_data = acpi_get_osc_data(handle); | |
64 | if (!osc_data) { | |
65 | printk(KERN_ERR "acpi osc data array is full\n"); | |
66 | - return AE_ERROR; | |
67 | + status = AE_ERROR; | |
68 | + goto out; | |
69 | } | |
70 | ||
71 | ctrlset = (flags & OSC_CONTROL_MASKS); | |
72 | - if (!ctrlset) | |
73 | - return AE_TYPE; | |
74 | + if (!ctrlset) { | |
75 | + status = AE_TYPE; | |
76 | + goto out; | |
77 | + } | |
78 | ||
79 | if (osc_data->is_queried && | |
80 | - ((osc_data->query_result & ctrlset) != ctrlset)) | |
81 | - return AE_SUPPORT; | |
82 | + ((osc_data->query_result & ctrlset) != ctrlset)) { | |
83 | + status = AE_SUPPORT; | |
84 | + goto out; | |
85 | + } | |
86 | ||
87 | control_set = osc_data->control_set | ctrlset; | |
88 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; | |
89 | @@ -211,7 +222,8 @@ acpi_status pci_osc_control_set(acpi_han | |
90 | status = acpi_run_osc(handle, &osc_args); | |
91 | if (ACPI_SUCCESS(status)) | |
92 | osc_data->control_set = control_set; | |
93 | - | |
94 | +out: | |
95 | + mutex_unlock(&pci_acpi_lock); | |
96 | return status; | |
97 | } | |
98 | EXPORT_SYMBOL(pci_osc_control_set); |