diff options
author | Shiju Jose <shiju.jose@huawei.com> | 2023-09-20 21:03:36 +0300 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2023-09-21 21:44:23 +0300 |
commit | e2abc47a5a1a9f641e7cacdca643fdd40729bf6e (patch) | |
tree | 971e7bc4ab175eda0f423a06e34a4c32308efae5 /include/acpi | |
parent | ce9ecca0238b140b88f43859b211c9fdfd8e5b70 (diff) | |
download | linux-e2abc47a5a1a9f641e7cacdca643fdd40729bf6e.tar.xz |
ACPI: APEI: Fix AER info corruption when error status data has multiple sections
ghes_handle_aer() passes AER data to the PCI core for logging and
recovery by calling aer_recover_queue() with a pointer to struct
aer_capability_regs.
The problem was that aer_recover_queue() queues the pointer directly
without copying the aer_capability_regs data. The pointer was to
the ghes->estatus buffer, which could be reused before
aer_recover_work_func() reads the data.
To avoid this problem, allocate a new aer_capability_regs structure
from the ghes_estatus_pool, copy the AER data from the ghes->estatus
buffer into it, pass a pointer to the new struct to
aer_recover_queue(), and free it after aer_recover_work_func() has
processed it.
Reported-by: Bjorn Helgaas <helgaas@kernel.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
[ rjw: Subject edits ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'include/acpi')
-rw-r--r-- | include/acpi/ghes.h | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 3c8bba9f1114..be1dd4c1a917 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -73,8 +73,12 @@ int ghes_register_vendor_record_notifier(struct notifier_block *nb); void ghes_unregister_vendor_record_notifier(struct notifier_block *nb); struct list_head *ghes_get_devices(void); + +void ghes_estatus_pool_region_free(unsigned long addr, u32 size); #else static inline struct list_head *ghes_get_devices(void) { return NULL; } + +static inline void ghes_estatus_pool_region_free(unsigned long addr, u32 size) { return; } #endif int ghes_estatus_pool_init(unsigned int num_ghes); |