From: Greg Kroah-Hartman Date: Wed, 17 May 2006 20:29:33 +0000 (-0700) Subject: add pciehp bugfix X-Git-Tag: v2.6.16.17~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cbf3caa585ecdbeb5d4c95a7a48673151dd03e14;p=thirdparty%2Fkernel%2Fstable-queue.git add pciehp bugfix --- diff --git a/queue-2.6.16/pci-correctly-allocate-return-buffers-for-osc-calls.patch b/queue-2.6.16/pci-correctly-allocate-return-buffers-for-osc-calls.patch new file mode 100644 index 00000000000..fad5e7c0160 --- /dev/null +++ b/queue-2.6.16/pci-correctly-allocate-return-buffers-for-osc-calls.patch @@ -0,0 +1,144 @@ +From owner-linux-pci@atrey.karlin.mff.cuni.cz Wed May 17 11:04:37 2006 +Subject: PCI: correctly allocate return buffers for osc calls +From: Kristen Accardi +To: linux-pci@atrey.karlin.mff.cuni.cz +Cc: linux-kernel@vger.kernel.org, greg@kroah.com +Date: Wed, 17 May 2006 11:13:37 -0700 +Message-Id: <1147889618.8472.6.camel@whizzy> + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-acpi.c | 60 ++++++++++++++++++++++++++++--------------------- + 1 file changed, 35 insertions(+), 25 deletions(-) + +--- linux-2.6.16.16.orig/drivers/pci/pci-acpi.c ++++ linux-2.6.16.16/drivers/pci/pci-acpi.c +@@ -33,13 +33,10 @@ acpi_query_osc ( + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; +- struct acpi_buffer output; +- union acpi_object out_obj; ++ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; ++ union acpi_object *out_obj; + u32 osc_dw0; + +- /* Setting up output buffer */ +- output.length = sizeof(out_obj) + 3*sizeof(u32); +- output.pointer = &out_obj; + + /* Setting up input parameters */ + input.count = 4; +@@ -61,12 +58,15 @@ acpi_query_osc ( + "Evaluate _OSC Set fails. Status = 0x%04x\n", status); + return status; + } +- if (out_obj.type != ACPI_TYPE_BUFFER) { ++ out_obj = output.pointer; ++ ++ if (out_obj->type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG + "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 & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request fails\n"); +@@ -76,15 +76,21 @@ acpi_query_osc ( + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + /* Update Global Control Set */ +- global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); +- return AE_OK; ++ global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); ++ status = AE_OK; ++ goto query_osc_out; + } +- return AE_ERROR; ++ status = AE_ERROR; ++ goto query_osc_out; + } + + /* Update Global Control Set */ +- global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); +- return AE_OK; ++ global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); ++ status = AE_OK; ++ ++query_osc_out: ++ kfree(output.pointer); ++ return status; + } + + +@@ -96,14 +102,10 @@ acpi_run_osc ( + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; +- struct acpi_buffer output; +- union acpi_object out_obj; ++ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; ++ union acpi_object *out_obj; + u32 osc_dw0; + +- /* Setting up output buffer */ +- output.length = sizeof(out_obj) + 3*sizeof(u32); +- output.pointer = &out_obj; +- + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; +@@ -124,12 +126,14 @@ acpi_run_osc ( + "Evaluate _OSC Set fails. Status = 0x%04x\n", status); + return status; + } +- if (out_obj.type != ACPI_TYPE_BUFFER) { ++ out_obj = output.pointer; ++ if (out_obj->type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG + "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 & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request fails\n"); +@@ -139,11 +143,17 @@ acpi_run_osc ( + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + 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; + } + + /** diff --git a/queue-2.6.16/series b/queue-2.6.16/series index 8df69f08e08..83b6790ba0e 100644 --- a/queue-2.6.16/series +++ b/queue-2.6.16/series @@ -9,3 +9,4 @@ scx200_acb-fix-resource-name-use-after-free.patch netfilter-do_add_counters-race-possible-info-leak.patch tg3-ethtool-always-report-port-is-tp.patch selinux-check-for-failed-kmalloc-in-security_sid_to_context.patch +pci-correctly-allocate-return-buffers-for-osc-calls.patch