Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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: 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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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__ */
+20 −11
Original line number Diff line number Diff line
@@ -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);
}

+0 −8
Original line number Diff line number Diff line
@@ -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,
+14 −1
Original line number Diff line number Diff line
@@ -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));
+33 −0
Original line number Diff line number Diff line
@@ -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);
}