mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
ACPICA: Tables: Mechanism to handle late stage acpi_get_table() imbalance
Considering this case:
1. A program opens a sysfs table file 65535 times, it can increase
validation_count and first increment cause the table to be mapped:
validation_count = 65535
2. AML execution causes "Load" to be executed on the same
table, this time it cannot increase validation_count, so
validation_count remains:
validation_count = 65535
3. The program closes sysfs table file 65535 times, it can decrease
validation_count and the last decrement cause the table to be
unmapped:
validation_count = 0
4. AML code still accessing the loaded table, kernel crash can be
observed.
To prevent that from happening, add a validation_count threashold.
When it is reached, the validation_count can no longer be
incremented/decremented to invalidate the table descriptor (means
preventing table unmappings)
Note that code added in acpi_tb_put_table() is actually a no-op but
changes the warning message into a "warn once" one. Lv Zheng.
Signed-off-by: Lv Zheng <[email protected]>
[ rjw: Changelog, comments ]
Signed-off-by: Rafael J. Wysocki <[email protected]>
This commit is contained in:
parent
186f0a0d8e
commit
83848fbe7e
2 changed files with 39 additions and 9 deletions
|
|
@ -416,9 +416,18 @@ acpi_tb_get_table(struct acpi_table_desc *table_desc,
|
|||
}
|
||||
}
|
||||
|
||||
table_desc->validation_count++;
|
||||
if (table_desc->validation_count == 0) {
|
||||
table_desc->validation_count--;
|
||||
if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
|
||||
table_desc->validation_count++;
|
||||
|
||||
/*
|
||||
* Detect validation_count overflows to ensure that the warning
|
||||
* message will only be printed once.
|
||||
*/
|
||||
if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Table %p, Validation count overflows\n",
|
||||
table_desc));
|
||||
}
|
||||
}
|
||||
|
||||
*out_table = table_desc->pointer;
|
||||
|
|
@ -445,13 +454,20 @@ void acpi_tb_put_table(struct acpi_table_desc *table_desc)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_tb_put_table);
|
||||
|
||||
if (table_desc->validation_count == 0) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Table %p, Validation count is zero before decrement\n",
|
||||
table_desc));
|
||||
return_VOID;
|
||||
if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
|
||||
table_desc->validation_count--;
|
||||
|
||||
/*
|
||||
* Detect validation_count underflows to ensure that the warning
|
||||
* message will only be printed once.
|
||||
*/
|
||||
if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Table %p, Validation count underflows\n",
|
||||
table_desc));
|
||||
return_VOID;
|
||||
}
|
||||
}
|
||||
table_desc->validation_count--;
|
||||
|
||||
if (table_desc->validation_count == 0) {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue