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

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

ACPICA: Prevent infinite loops when traversing corrupted lists.



This change hardens the ACPICA code to detect circular linked object
lists and prevent an infinite loop if such corruption exists.

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 a487af33
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
{
	union acpi_operand_object *handler_obj;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *start_desc;
	union acpi_operand_object **last_obj_ptr;
	acpi_adr_space_setup region_setup;
	void **region_context;
@@ -341,6 +342,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
	/* Find this region in the handler's list */

	obj_desc = handler_obj->address_space.region_list;
	start_desc = obj_desc;
	last_obj_ptr = &handler_obj->address_space.region_list;

	while (obj_desc) {
@@ -438,6 +440,15 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,

		last_obj_ptr = &obj_desc->region.next;
		obj_desc = obj_desc->region.next;

		/* Prevent infinite loop if list is corrupted */

		if (obj_desc == start_desc) {
			ACPI_ERROR((AE_INFO,
				    "Circular handler list in region object %p",
				    region_obj));
			return_VOID;
		}
	}

	/* If we get here, the region was not in the handler's region list */
+8 −2
Original line number Diff line number Diff line
@@ -222,13 +222,19 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node)
		}
	}

	/* Clear the entry in all cases */
	/* Clear the Node entry in all cases */

	node->object = NULL;
	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {

		/* Unlink object from front of possible object list */

		node->object = obj_desc->common.next_object;

		/* Handle possible 2-descriptor object */

		if (node->object &&
		    ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) {
		    (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
			node->object = node->object->common.next_object;
		}
	}
+13 −2
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
	union acpi_operand_object *handler_desc;
	union acpi_operand_object *second_desc;
	union acpi_operand_object *next_desc;
	union acpi_operand_object *start_desc;
	union acpi_operand_object **last_obj_ptr;

	ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object);
@@ -235,10 +236,11 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
			if (handler_desc) {
				next_desc =
				    handler_desc->address_space.region_list;
				start_desc = next_desc;
				last_obj_ptr =
				    &handler_desc->address_space.region_list;

				/* Remove the region object from the handler's list */
				/* Remove the region object from the handler list */

				while (next_desc) {
					if (next_desc == object) {
@@ -247,10 +249,19 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
						break;
					}

					/* Walk the linked list of handler */
					/* Walk the linked list of handlers */

					last_obj_ptr = &next_desc->region.next;
					next_desc = next_desc->region.next;

					/* Prevent infinite loop if list is corrupted */

					if (next_desc == start_desc) {
						ACPI_ERROR((AE_INFO,
							    "Circular region list in address handler object %p",
							    handler_desc));
						return_VOID;
					}
				}

				if (handler_desc->address_space.handler_flags &