Skip to content

Commit

Permalink
ACPICA: Prevent infinite loops when traversing corrupted lists.
Browse files Browse the repository at this point in the history
This change hardens the ACPICA code to detect circular linked object
lists and prevent an infinite loop if such corruption exists.

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 Mar 18, 2014
1 parent a487af3 commit f953529
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
11 changes: 11 additions & 0 deletions drivers/acpi/acpica/evregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 */
Expand Down
10 changes: 8 additions & 2 deletions drivers/acpi/acpica/nsobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
15 changes: 13 additions & 2 deletions drivers/acpi/acpica/utdelete.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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 &
Expand Down

0 comments on commit f953529

Please sign in to comment.