diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-15 04:51:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-15 04:51:19 -0400 |
commit | 35e60a6b7577218ac7eb7777c8849822a080e127 (patch) | |
tree | a1578093e1e88e17a53ac7b99b0638bd110e04ee | |
parent | 92091c438bad93ba2591e8c4ba86126227327be2 (diff) | |
parent | 9522933454f4c4bd5bedf3d71c538708b7c5de5b (diff) |
Merge tag 'acpi-4.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI fixes from Rafael Wysocki:
"These revert an ACPICA commit from the 4.11 cycle that causes problems
to happen on some systems and add a protection against possible kernel
crashes due to table reference counter imbalance.
Specifics:
- Revert a 4.11 ACPICA change that made assumptions which are not
satisfied on some systems and caused the enumeration of resources
to fail on them (Rafael Wysocki).
- Add a mechanism to prevent tables from being unmapped prematurely
due to reference counter overflows (Lv Zheng)"
* tag 'acpi-4.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPICA: Tables: Mechanism to handle late stage acpi_get_table() imbalance
Revert "ACPICA: Disassembler: Enhance resource descriptor detection"
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 34 | ||||
-rw-r--r-- | drivers/acpi/acpica/utresrc.c | 9 | ||||
-rw-r--r-- | include/acpi/actbl.h | 14 |
3 files changed, 39 insertions, 18 deletions
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 7abe66505739..0d2e98920069 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -416,9 +416,18 @@ acpi_tb_get_table(struct acpi_table_desc *table_desc, | |||
416 | } | 416 | } |
417 | } | 417 | } |
418 | 418 | ||
419 | table_desc->validation_count++; | 419 | if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) { |
420 | if (table_desc->validation_count == 0) { | 420 | table_desc->validation_count++; |
421 | table_desc->validation_count--; | 421 | |
422 | /* | ||
423 | * Detect validation_count overflows to ensure that the warning | ||
424 | * message will only be printed once. | ||
425 | */ | ||
426 | if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) { | ||
427 | ACPI_WARNING((AE_INFO, | ||
428 | "Table %p, Validation count overflows\n", | ||
429 | table_desc)); | ||
430 | } | ||
422 | } | 431 | } |
423 | 432 | ||
424 | *out_table = table_desc->pointer; | 433 | *out_table = table_desc->pointer; |
@@ -445,13 +454,20 @@ void acpi_tb_put_table(struct acpi_table_desc *table_desc) | |||
445 | 454 | ||
446 | ACPI_FUNCTION_TRACE(acpi_tb_put_table); | 455 | ACPI_FUNCTION_TRACE(acpi_tb_put_table); |
447 | 456 | ||
448 | if (table_desc->validation_count == 0) { | 457 | if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) { |
449 | ACPI_WARNING((AE_INFO, | 458 | table_desc->validation_count--; |
450 | "Table %p, Validation count is zero before decrement\n", | 459 | |
451 | table_desc)); | 460 | /* |
452 | return_VOID; | 461 | * Detect validation_count underflows to ensure that the warning |
462 | * message will only be printed once. | ||
463 | */ | ||
464 | if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) { | ||
465 | ACPI_WARNING((AE_INFO, | ||
466 | "Table %p, Validation count underflows\n", | ||
467 | table_desc)); | ||
468 | return_VOID; | ||
469 | } | ||
453 | } | 470 | } |
454 | table_desc->validation_count--; | ||
455 | 471 | ||
456 | if (table_desc->validation_count == 0) { | 472 | if (table_desc->validation_count == 0) { |
457 | 473 | ||
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index e0587c85bafd..ff096d9755b9 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c | |||
@@ -474,15 +474,6 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, | |||
474 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); | 474 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); |
475 | } | 475 | } |
476 | 476 | ||
477 | /* | ||
478 | * The end_tag opcode must be followed by a zero byte. | ||
479 | * Although this byte is technically defined to be a checksum, | ||
480 | * in practice, all ASL compilers set this byte to zero. | ||
481 | */ | ||
482 | if (*(aml + 1) != 0) { | ||
483 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); | ||
484 | } | ||
485 | |||
486 | /* Return the pointer to the end_tag if requested */ | 477 | /* Return the pointer to the end_tag if requested */ |
487 | 478 | ||
488 | if (!user_function) { | 479 | if (!user_function) { |
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index d92543f3bbfd..bdc55c0da19c 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h | |||
@@ -374,6 +374,20 @@ struct acpi_table_desc { | |||
374 | u16 validation_count; | 374 | u16 validation_count; |
375 | }; | 375 | }; |
376 | 376 | ||
377 | /* | ||
378 | * Maximum value of the validation_count field in struct acpi_table_desc. | ||
379 | * When reached, validation_count cannot be changed any more and the table will | ||
380 | * be permanently regarded as validated. | ||
381 | * | ||
382 | * This is to prevent situations in which unbalanced table get/put operations | ||
383 | * may cause premature table unmapping in the OS to happen. | ||
384 | * | ||
385 | * The maximum validation count can be defined to any value, but should be | ||
386 | * greater than the maximum number of OS early stage mapping slots to avoid | ||
387 | * leaking early stage table mappings to the late stage. | ||
388 | */ | ||
389 | #define ACPI_MAX_TABLE_VALIDATIONS ACPI_UINT16_MAX | ||
390 | |||
377 | /* Masks for Flags field above */ | 391 | /* Masks for Flags field above */ |
378 | 392 | ||
379 | #define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL (0) /* Virtual address, external maintained */ | 393 | #define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL (0) /* Virtual address, external maintained */ |