Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / acpi / executer / exconfig.c
index a0f34b4..39d7421 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2007, R. Byron Moore
+ * Copyright (C) 2000 - 2008, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,6 @@
 #include <acpi/acinterp.h>
 #include <acpi/amlcode.h>
 #include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
 #include <acpi/actables.h>
 #include <acpi/acdispat.h>
 
@@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
 
        ACPI_FUNCTION_TRACE(ex_load_table_op);
 
+       /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */
+
+       if ((operand[0]->string.length > ACPI_NAME_SIZE) ||
+           (operand[1]->string.length > ACPI_OEM_ID_SIZE) ||
+           (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
        /* Find the ACPI table in the RSDT/XSDT */
 
        status = acpi_tb_find_table(operand[0]->string.pointer,
@@ -229,7 +236,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
        status = acpi_get_table_by_index(table_index, &table);
        if (ACPI_SUCCESS(status)) {
                ACPI_INFO((AE_INFO,
-                          "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]",
+                          "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
                           table->signature, table->oem_id,
                           table->oem_table_id));
        }
@@ -275,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
        struct acpi_table_desc table_desc;
        acpi_native_uint table_index;
        acpi_status status;
+       u32 length;
 
        ACPI_FUNCTION_TRACE(ex_load_op);
 
@@ -322,18 +330,36 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
                                  "Load from Buffer or Field %p %s\n", obj_desc,
                                  acpi_ut_get_object_type_name(obj_desc)));
 
+               length = obj_desc->buffer.length;
+
+               /* Must have at least an ACPI table header */
+
+               if (length < sizeof(struct acpi_table_header)) {
+                       return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
+               }
+
+               /* Validate checksum here. It won't get validated in tb_add_table */
+
+               status =
+                   acpi_tb_verify_checksum(ACPI_CAST_PTR
+                                           (struct acpi_table_header,
+                                            obj_desc->buffer.pointer), length);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+
                /*
                 * We need to copy the buffer since the original buffer could be
                 * changed or deleted in the future
                 */
-               table_desc.pointer = ACPI_ALLOCATE(obj_desc->buffer.length);
+               table_desc.pointer = ACPI_ALLOCATE(length);
                if (!table_desc.pointer) {
                        return_ACPI_STATUS(AE_NO_MEMORY);
                }
 
                ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
-                           obj_desc->buffer.length);
-               table_desc.length = obj_desc->buffer.length;
+                           length);
+               table_desc.length = length;
                table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
                break;
 
@@ -349,6 +375,13 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
                goto cleanup;
        }
 
+       /*
+        * Add the table to the namespace.
+        *
+        * Note: We load the table objects relative to the root of the namespace.
+        * This appears to go against the ACPI specification, but we do it for
+        * compatibility with other ACPI implementations.
+        */
        status =
            acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
        if (ACPI_FAILURE(status)) {
@@ -441,12 +474,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
         * (Offset contains the table_id)
         */
        acpi_tb_delete_namespace_by_owner(table_index);
-       acpi_tb_release_owner_id(table_index);
+       (void)acpi_tb_release_owner_id(table_index);
 
        acpi_tb_set_table_loaded_flag(table_index, FALSE);
 
-       /* Delete the table descriptor (ddb_handle) */
-
-       acpi_ut_remove_reference(table_desc);
        return_ACPI_STATUS(AE_OK);
 }