diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 7e0b6f1bec9c98fde5ca20b9ea379bc2e6c49a88..58497b7e33472c72e31c7fe7fa525df3aa377354 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -164,4 +164,6 @@ acpi_tb_install_fixed_table(acpi_physical_address address, acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); +u8 acpi_is_valid_signature(char *signature); + #endif /* __ACTABLES_H__ */ diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index ea0cc4e08f8033c8acc230657d6d425a2a801510..81d7b9863e3213855790536b41b550a48e727375 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -480,8 +480,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, union acpi_operand_object **operand; struct acpi_namespace_node *node; union acpi_parse_object *next_op; - u32 table_index; struct acpi_table_header *table; + u32 table_index; ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); @@ -504,6 +504,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + operand = &walk_state->operands[0]; + /* * Resolve the Signature string, oem_id string, * and oem_table_id string operands @@ -511,32 +513,34 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } - operand = &walk_state->operands[0]; - /* Find the ACPI table */ status = acpi_tb_find_table(operand[0]->string.pointer, operand[1]->string.pointer, operand[2]->string.pointer, &table_index); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (status == AE_NOT_FOUND) { + ACPI_ERROR((AE_INFO, + "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", + operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer)); + } + goto cleanup; } - acpi_ut_remove_reference(operand[0]); - acpi_ut_remove_reference(operand[1]); - acpi_ut_remove_reference(operand[2]); - status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); + status = AE_NOT_EXIST; + goto cleanup; } obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); @@ -551,6 +555,11 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, obj_desc->region.flags |= AOPOBJ_DATA_VALID; +cleanup: + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 24a4c5c2b124825b5616371882ffa0f9666cdc85..b540913c11acebdb2bb9ee16e9915445a58dd40f 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -162,14 +162,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Validate lengths for the Signature, oem_id, and oem_table_id strings */ - - 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_AML_STRING_LIMIT); - } - /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index 119c84ad98334e2404fb72e585c4ec30ee49c684..405529d49a1ab83d20387900682c3a983d7c7a67 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -68,12 +68,25 @@ acpi_status acpi_tb_find_table(char *signature, char *oem_id, char *oem_table_id, u32 *table_index) { - u32 i; acpi_status status; struct acpi_table_header header; + u32 i; ACPI_FUNCTION_TRACE(tb_find_table); + /* Validate the input table signature */ + + if (!acpi_is_valid_signature(signature)) { + return_ACPI_STATUS(AE_BAD_SIGNATURE); + } + + /* Don't allow the OEM strings to be too long */ + + if ((strlen(oem_id) > ACPI_OEM_ID_SIZE) || + (strlen(oem_table_id) > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_AML_STRING_LIMIT); + } + /* Normalize the input strings */ memset(&header, 0, sizeof(struct acpi_table_header)); diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 568ac0e4a3c6a784efe38349213c26146888f6d5..db7f2aa9a457d7e63aded8bf014dbcb07896ba62 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -412,3 +412,36 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) return_ACPI_STATUS(AE_OK); } + +/******************************************************************************* + * + * FUNCTION: acpi_is_valid_signature + * + * PARAMETERS: signature - Sig string to be validated + * + * RETURN: TRUE if signature is correct length and has valid characters + * + * DESCRIPTION: Validate an ACPI table signature. + * + ******************************************************************************/ + +u8 acpi_is_valid_signature(char *signature) +{ + u32 i; + + /* Validate the signature length */ + + if (strlen(signature) != ACPI_NAME_SIZE) { + return (FALSE); + } + + /* Validate each character in the signature */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char(signature[i], i)) { + return (FALSE); + } + } + + return (TRUE); +}