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: 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
a487af33a4
commit
f953529f3b
3 changed files with 32 additions and 4 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 &
|
||||
|
|
Loading…
Reference in a new issue