]>
Commit | Line | Data |
---|---|---|
cbf3caa5 GKH |
1 | From owner-linux-pci@atrey.karlin.mff.cuni.cz Wed May 17 11:04:37 2006 |
2 | Subject: PCI: correctly allocate return buffers for osc calls | |
3 | From: Kristen Accardi <kristen.c.accardi@intel.com> | |
4 | To: linux-pci@atrey.karlin.mff.cuni.cz | |
5 | Cc: linux-kernel@vger.kernel.org, greg@kroah.com | |
6 | Date: Wed, 17 May 2006 11:13:37 -0700 | |
7 | Message-Id: <1147889618.8472.6.camel@whizzy> | |
8 | ||
9 | The OSC set and query functions do not allocate enough space for return values, | |
10 | and set the output buffer length to a false, too large value. This causes the | |
11 | acpi-ca code to assume that the output buffer is larger than it actually is, | |
12 | and overwrite memory when copying acpi return buffers into this caller provided | |
13 | buffer. In some cases this can cause kernel oops if the memory that is | |
14 | overwritten is a pointer. This patch will change these calls to use a | |
15 | dynamically allocated output buffer, thus allowing the acpi-ca code to decide | |
16 | how much space is needed. | |
17 | ||
18 | Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> | |
19 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
70a83a42 | 20 | Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
cbf3caa5 GKH |
21 | |
22 | --- | |
23 | drivers/pci/pci-acpi.c | 60 ++++++++++++++++++++++++++++--------------------- | |
24 | 1 file changed, 35 insertions(+), 25 deletions(-) | |
25 | ||
26 | --- linux-2.6.16.16.orig/drivers/pci/pci-acpi.c | |
27 | +++ linux-2.6.16.16/drivers/pci/pci-acpi.c | |
28 | @@ -33,13 +33,10 @@ acpi_query_osc ( | |
29 | acpi_status status; | |
30 | struct acpi_object_list input; | |
31 | union acpi_object in_params[4]; | |
32 | - struct acpi_buffer output; | |
33 | - union acpi_object out_obj; | |
34 | + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | |
35 | + union acpi_object *out_obj; | |
36 | u32 osc_dw0; | |
37 | ||
38 | - /* Setting up output buffer */ | |
39 | - output.length = sizeof(out_obj) + 3*sizeof(u32); | |
40 | - output.pointer = &out_obj; | |
41 | ||
42 | /* Setting up input parameters */ | |
43 | input.count = 4; | |
44 | @@ -61,12 +58,15 @@ acpi_query_osc ( | |
45 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); | |
46 | return status; | |
47 | } | |
48 | - if (out_obj.type != ACPI_TYPE_BUFFER) { | |
49 | + out_obj = output.pointer; | |
50 | + | |
51 | + if (out_obj->type != ACPI_TYPE_BUFFER) { | |
52 | printk(KERN_DEBUG | |
53 | "Evaluate _OSC returns wrong type\n"); | |
54 | - return AE_TYPE; | |
55 | + status = AE_TYPE; | |
56 | + goto query_osc_out; | |
57 | } | |
58 | - osc_dw0 = *((u32 *) out_obj.buffer.pointer); | |
59 | + osc_dw0 = *((u32 *) out_obj->buffer.pointer); | |
60 | if (osc_dw0) { | |
61 | if (osc_dw0 & OSC_REQUEST_ERROR) | |
62 | printk(KERN_DEBUG "_OSC request fails\n"); | |
63 | @@ -76,15 +76,21 @@ acpi_query_osc ( | |
64 | printk(KERN_DEBUG "_OSC invalid revision\n"); | |
65 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | |
66 | /* Update Global Control Set */ | |
67 | - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); | |
68 | - return AE_OK; | |
69 | + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); | |
70 | + status = AE_OK; | |
71 | + goto query_osc_out; | |
72 | } | |
73 | - return AE_ERROR; | |
74 | + status = AE_ERROR; | |
75 | + goto query_osc_out; | |
76 | } | |
77 | ||
78 | /* Update Global Control Set */ | |
79 | - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); | |
80 | - return AE_OK; | |
81 | + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); | |
82 | + status = AE_OK; | |
83 | + | |
84 | +query_osc_out: | |
85 | + kfree(output.pointer); | |
86 | + return status; | |
87 | } | |
88 | ||
89 | ||
90 | @@ -96,14 +102,10 @@ acpi_run_osc ( | |
91 | acpi_status status; | |
92 | struct acpi_object_list input; | |
93 | union acpi_object in_params[4]; | |
94 | - struct acpi_buffer output; | |
95 | - union acpi_object out_obj; | |
96 | + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | |
97 | + union acpi_object *out_obj; | |
98 | u32 osc_dw0; | |
99 | ||
100 | - /* Setting up output buffer */ | |
101 | - output.length = sizeof(out_obj) + 3*sizeof(u32); | |
102 | - output.pointer = &out_obj; | |
103 | - | |
104 | /* Setting up input parameters */ | |
105 | input.count = 4; | |
106 | input.pointer = in_params; | |
107 | @@ -124,12 +126,14 @@ acpi_run_osc ( | |
108 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); | |
109 | return status; | |
110 | } | |
111 | - if (out_obj.type != ACPI_TYPE_BUFFER) { | |
112 | + out_obj = output.pointer; | |
113 | + if (out_obj->type != ACPI_TYPE_BUFFER) { | |
114 | printk(KERN_DEBUG | |
115 | "Evaluate _OSC returns wrong type\n"); | |
116 | - return AE_TYPE; | |
117 | + status = AE_TYPE; | |
118 | + goto run_osc_out; | |
119 | } | |
120 | - osc_dw0 = *((u32 *) out_obj.buffer.pointer); | |
121 | + osc_dw0 = *((u32 *) out_obj->buffer.pointer); | |
122 | if (osc_dw0) { | |
123 | if (osc_dw0 & OSC_REQUEST_ERROR) | |
124 | printk(KERN_DEBUG "_OSC request fails\n"); | |
125 | @@ -139,11 +143,17 @@ acpi_run_osc ( | |
126 | printk(KERN_DEBUG "_OSC invalid revision\n"); | |
127 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | |
128 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); | |
129 | - return AE_SUPPORT; | |
130 | + status = AE_SUPPORT; | |
131 | + goto run_osc_out; | |
132 | } | |
133 | - return AE_ERROR; | |
134 | + status = AE_ERROR; | |
135 | + goto run_osc_out; | |
136 | } | |
137 | - return AE_OK; | |
138 | + status = AE_OK; | |
139 | + | |
140 | +run_osc_out: | |
141 | + kfree(output.pointer); | |
142 | + return status; | |
143 | } | |
144 | ||
145 | /** |