提交 593ee207 编写于 作者: K Kristen Accardi 提交者: Linus Torvalds

[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: NKristen 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: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 d66fd908
...@@ -33,13 +33,10 @@ acpi_query_osc ( ...@@ -33,13 +33,10 @@ acpi_query_osc (
acpi_status status; acpi_status status;
struct acpi_object_list input; struct acpi_object_list input;
union acpi_object in_params[4]; union acpi_object in_params[4];
struct acpi_buffer output; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object out_obj; union acpi_object *out_obj;
u32 osc_dw0; u32 osc_dw0;
/* Setting up output buffer */
output.length = sizeof(out_obj) + 3*sizeof(u32);
output.pointer = &out_obj;
/* Setting up input parameters */ /* Setting up input parameters */
input.count = 4; input.count = 4;
...@@ -61,12 +58,15 @@ acpi_query_osc ( ...@@ -61,12 +58,15 @@ acpi_query_osc (
"Evaluate _OSC Set fails. Status = 0x%04x\n", status); "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status; return status;
} }
if (out_obj.type != ACPI_TYPE_BUFFER) { out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n"); "Evaluate _OSC returns wrong type\n");
return AE_TYPE; status = AE_TYPE;
goto query_osc_out;
} }
osc_dw0 = *((u32 *) out_obj.buffer.pointer); osc_dw0 = *((u32 *) out_obj->buffer.pointer);
if (osc_dw0) { if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR) if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n"); printk(KERN_DEBUG "_OSC request fails\n");
...@@ -76,15 +76,21 @@ acpi_query_osc ( ...@@ -76,15 +76,21 @@ acpi_query_osc (
printk(KERN_DEBUG "_OSC invalid revision\n"); printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
/* Update Global Control Set */ /* Update Global Control Set */
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8));
return AE_OK; status = AE_OK;
goto query_osc_out;
} }
return AE_ERROR; status = AE_ERROR;
goto query_osc_out;
} }
/* Update Global Control Set */ /* Update Global Control Set */
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
return AE_OK; status = AE_OK;
query_osc_out:
kfree(output.pointer);
return status;
} }
...@@ -96,14 +102,10 @@ acpi_run_osc ( ...@@ -96,14 +102,10 @@ acpi_run_osc (
acpi_status status; acpi_status status;
struct acpi_object_list input; struct acpi_object_list input;
union acpi_object in_params[4]; union acpi_object in_params[4];
struct acpi_buffer output; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object out_obj; union acpi_object *out_obj;
u32 osc_dw0; u32 osc_dw0;
/* Setting up output buffer */
output.length = sizeof(out_obj) + 3*sizeof(u32);
output.pointer = &out_obj;
/* Setting up input parameters */ /* Setting up input parameters */
input.count = 4; input.count = 4;
input.pointer = in_params; input.pointer = in_params;
...@@ -124,12 +126,14 @@ acpi_run_osc ( ...@@ -124,12 +126,14 @@ acpi_run_osc (
"Evaluate _OSC Set fails. Status = 0x%04x\n", status); "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status; return status;
} }
if (out_obj.type != ACPI_TYPE_BUFFER) { out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n"); "Evaluate _OSC returns wrong type\n");
return AE_TYPE; status = AE_TYPE;
goto run_osc_out;
} }
osc_dw0 = *((u32 *) out_obj.buffer.pointer); osc_dw0 = *((u32 *) out_obj->buffer.pointer);
if (osc_dw0) { if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR) if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n"); printk(KERN_DEBUG "_OSC request fails\n");
...@@ -139,11 +143,17 @@ acpi_run_osc ( ...@@ -139,11 +143,17 @@ acpi_run_osc (
printk(KERN_DEBUG "_OSC invalid revision\n"); printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
printk(KERN_DEBUG "_OSC FW not grant req. control\n"); printk(KERN_DEBUG "_OSC FW not grant req. control\n");
return AE_SUPPORT; status = AE_SUPPORT;
goto run_osc_out;
} }
return AE_ERROR; status = AE_ERROR;
goto run_osc_out;
} }
return AE_OK; status = AE_OK;
run_osc_out:
kfree(output.pointer);
return status;
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册