Commit 9f41fd8a authored by Bob Moore's avatar Bob Moore Committed by Rafael J. Wysocki

ACPICA: Update parameter validation for data_table_region and load_table

ACPICA commit 51ab555e60b4a3de3cc4a846e86d0de255be441a

Add additional validation for the table signature and
the OEM strings. Eliminates buffer read overrun in data_table_region.
ACPICA BZ 1184.

Link: https://bugs.acpica.org/show_bug.cgi?id=1184
Link: https://github.com/acpica/acpica/commit/51ab555eSigned-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 35349697
...@@ -164,4 +164,6 @@ acpi_tb_install_fixed_table(acpi_physical_address address, ...@@ -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); acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
u8 acpi_is_valid_signature(char *signature);
#endif /* __ACTABLES_H__ */ #endif /* __ACTABLES_H__ */
...@@ -480,8 +480,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, ...@@ -480,8 +480,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_operand_object **operand; union acpi_operand_object **operand;
struct acpi_namespace_node *node; struct acpi_namespace_node *node;
union acpi_parse_object *next_op; union acpi_parse_object *next_op;
u32 table_index;
struct acpi_table_header *table; struct acpi_table_header *table;
u32 table_index;
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); 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, ...@@ -504,6 +504,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
operand = &walk_state->operands[0];
/* /*
* Resolve the Signature string, oem_id string, * Resolve the Signature string, oem_id string,
* and oem_table_id string operands * and oem_table_id string operands
...@@ -511,32 +513,34 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, ...@@ -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, status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state); ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); goto cleanup;
} }
operand = &walk_state->operands[0];
/* Find the ACPI table */ /* Find the ACPI table */
status = acpi_tb_find_table(operand[0]->string.pointer, status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer, operand[1]->string.pointer,
operand[2]->string.pointer, &table_index); operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) { 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); status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); goto cleanup;
} }
obj_desc = acpi_ns_get_attached_object(node); obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) { if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST); status = AE_NOT_EXIST;
goto cleanup;
} }
obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); 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, ...@@ -551,6 +555,11 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
obj_desc->region.flags |= AOPOBJ_DATA_VALID; 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); return_ACPI_STATUS(status);
} }
......
...@@ -162,14 +162,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ...@@ -162,14 +162,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE(ex_load_table_op); 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 */ /* Find the ACPI table in the RSDT/XSDT */
status = acpi_tb_find_table(operand[0]->string.pointer, status = acpi_tb_find_table(operand[0]->string.pointer,
......
...@@ -68,12 +68,25 @@ acpi_status ...@@ -68,12 +68,25 @@ acpi_status
acpi_tb_find_table(char *signature, acpi_tb_find_table(char *signature,
char *oem_id, char *oem_table_id, u32 *table_index) char *oem_id, char *oem_table_id, u32 *table_index)
{ {
u32 i;
acpi_status status; acpi_status status;
struct acpi_table_header header; struct acpi_table_header header;
u32 i;
ACPI_FUNCTION_TRACE(tb_find_table); 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 */ /* Normalize the input strings */
memset(&header, 0, sizeof(struct acpi_table_header)); memset(&header, 0, sizeof(struct acpi_table_header));
......
...@@ -412,3 +412,36 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -412,3 +412,36 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
return_ACPI_STATUS(AE_OK); 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment