aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristen Accardi <kristen.c.accardi@intel.com>2006-05-20 18:00:08 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-05-21 15:59:18 -0400
commit593ee20766921fec643194dff829e17f30552220 (patch)
tree78fe75485a921e80252184d52613280cef5e9dbd
parentd66fd908acc8ba88541ecc570d89b0243f947c5e (diff)
[PATCH] pci: correctly allocate return buffers for osc calls
The OSC set and query functions do not allocate enough space for return values, and set the output buffer length to a false, too large value. This causes the acpi-ca code to assume that the output buffer is larger than it actually is, and overwrite memory when copying acpi return buffers into this caller provided buffer. In some cases this can cause kernel oops if the memory that is overwritten is a pointer. This patch will change these calls to use a dynamically allocated output buffer, thus allowing the acpi-ca code to decide how much space is needed. Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Cc: "Brown, Len" <len.brown@intel.com> Cc: "Yu, Luming" <luming.yu@intel.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/pci/pci-acpi.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 6917c6cb0912..c2ecae5ff0c1 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -33,13 +33,10 @@ acpi_query_osc (
33 acpi_status status; 33 acpi_status status;
34 struct acpi_object_list input; 34 struct acpi_object_list input;
35 union acpi_object in_params[4]; 35 union acpi_object in_params[4];
36 struct acpi_buffer output; 36 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
37 union acpi_object out_obj; 37 union acpi_object *out_obj;
38 u32 osc_dw0; 38 u32 osc_dw0;
39 39
40 /* Setting up output buffer */
41 output.length = sizeof(out_obj) + 3*sizeof(u32);
42 output.pointer = &out_obj;
43 40
44 /* Setting up input parameters */ 41 /* Setting up input parameters */
45 input.count = 4; 42 input.count = 4;
@@ -61,12 +58,15 @@ acpi_query_osc (
61 "Evaluate _OSC Set fails. Status = 0x%04x\n", status); 58 "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
62 return status; 59 return status;
63 } 60 }
64 if (out_obj.type != ACPI_TYPE_BUFFER) { 61 out_obj = output.pointer;
62
63 if (out_obj->type != ACPI_TYPE_BUFFER) {
65 printk(KERN_DEBUG 64 printk(KERN_DEBUG
66 "Evaluate _OSC returns wrong type\n"); 65 "Evaluate _OSC returns wrong type\n");
67 return AE_TYPE; 66 status = AE_TYPE;
67 goto query_osc_out;
68 } 68 }
69 osc_dw0 = *((u32 *) out_obj.buffer.pointer); 69 osc_dw0 = *((u32 *) out_obj->buffer.pointer);
70 if (osc_dw0) { 70 if (osc_dw0) {
71 if (osc_dw0 & OSC_REQUEST_ERROR) 71 if (osc_dw0 & OSC_REQUEST_ERROR)
72 printk(KERN_DEBUG "_OSC request fails\n"); 72 printk(KERN_DEBUG "_OSC request fails\n");
@@ -76,15 +76,21 @@ acpi_query_osc (
76 printk(KERN_DEBUG "_OSC invalid revision\n"); 76 printk(KERN_DEBUG "_OSC invalid revision\n");
77 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 77 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
78 /* Update Global Control Set */ 78 /* Update Global Control Set */
79 global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); 79 global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8));
80 return AE_OK; 80 status = AE_OK;
81 goto query_osc_out;
81 } 82 }
82 return AE_ERROR; 83 status = AE_ERROR;
84 goto query_osc_out;
83 } 85 }
84 86
85 /* Update Global Control Set */ 87 /* Update Global Control Set */
86 global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); 88 global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
87 return AE_OK; 89 status = AE_OK;
90
91query_osc_out:
92 kfree(output.pointer);
93 return status;
88} 94}
89 95
90 96
@@ -96,14 +102,10 @@ acpi_run_osc (
96 acpi_status status; 102 acpi_status status;
97 struct acpi_object_list input; 103 struct acpi_object_list input;
98 union acpi_object in_params[4]; 104 union acpi_object in_params[4];
99 struct acpi_buffer output; 105 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
100 union acpi_object out_obj; 106 union acpi_object *out_obj;
101 u32 osc_dw0; 107 u32 osc_dw0;
102 108
103 /* Setting up output buffer */
104 output.length = sizeof(out_obj) + 3*sizeof(u32);
105 output.pointer = &out_obj;
106
107 /* Setting up input parameters */ 109 /* Setting up input parameters */
108 input.count = 4; 110 input.count = 4;
109 input.pointer = in_params; 111 input.pointer = in_params;
@@ -124,12 +126,14 @@ acpi_run_osc (
124 "Evaluate _OSC Set fails. Status = 0x%04x\n", status); 126 "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
125 return status; 127 return status;
126 } 128 }
127 if (out_obj.type != ACPI_TYPE_BUFFER) { 129 out_obj = output.pointer;
130 if (out_obj->type != ACPI_TYPE_BUFFER) {
128 printk(KERN_DEBUG 131 printk(KERN_DEBUG
129 "Evaluate _OSC returns wrong type\n"); 132 "Evaluate _OSC returns wrong type\n");
130 return AE_TYPE; 133 status = AE_TYPE;
134 goto run_osc_out;
131 } 135 }
132 osc_dw0 = *((u32 *) out_obj.buffer.pointer); 136 osc_dw0 = *((u32 *) out_obj->buffer.pointer);
133 if (osc_dw0) { 137 if (osc_dw0) {
134 if (osc_dw0 & OSC_REQUEST_ERROR) 138 if (osc_dw0 & OSC_REQUEST_ERROR)
135 printk(KERN_DEBUG "_OSC request fails\n"); 139 printk(KERN_DEBUG "_OSC request fails\n");
@@ -139,11 +143,17 @@ acpi_run_osc (
139 printk(KERN_DEBUG "_OSC invalid revision\n"); 143 printk(KERN_DEBUG "_OSC invalid revision\n");
140 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 144 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
141 printk(KERN_DEBUG "_OSC FW not grant req. control\n"); 145 printk(KERN_DEBUG "_OSC FW not grant req. control\n");
142 return AE_SUPPORT; 146 status = AE_SUPPORT;
147 goto run_osc_out;
143 } 148 }
144 return AE_ERROR; 149 status = AE_ERROR;
150 goto run_osc_out;
145 } 151 }
146 return AE_OK; 152 status = AE_OK;
153
154run_osc_out:
155 kfree(output.pointer);
156 return status;
147} 157}
148 158
149/** 159/**