forked from Minki/linux
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/51ab555e Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
3534969721
commit
9f41fd8a17
@ -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__ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -412,3 +412,36 @@ next_table:
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user