Skip to content

Commit

Permalink
ACPICA: Update parameter validation for data_table_region and load_table
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bob Moore authored and Rafael J. Wysocki committed Aug 25, 2015
1 parent 3534969 commit 9f41fd8
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 20 deletions.
2 changes: 2 additions & 0 deletions drivers/acpi/acpica/actables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
31 changes: 20 additions & 11 deletions drivers/acpi/acpica/dsopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -504,39 +504,43 @@ 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
*/
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);
Expand All @@ -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);
}

Expand Down
8 changes: 0 additions & 8 deletions drivers/acpi/acpica/exconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
15 changes: 14 additions & 1 deletion drivers/acpi/acpica/tbfind.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
33 changes: 33 additions & 0 deletions drivers/acpi/acpica/tbutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit 9f41fd8

Please sign in to comment.