ACPI: extlog: Avoid populating software AER metadata from raw hardware buffer

extlog_print_pcie() casts pcie_err->aer_info straight to struct
aer_capability_regs *. That struct embeds struct pcie_tlp_log, whose
software-only header_len and flit fields sit at offset 84 - inside the
96-byte aer_info buffer - so the cast fills them with raw firmware bytes.
pcie_print_tlp_log() uses both to bound a loop over dw[], and a large
header_len walks past the end of the array.

Copy into a zeroed local struct, and only as far as aer_info maps onto it:
the leading registers and the four Header Log DWORDs. Place the TLP Prefix
Log separately, from the offset the hardware keeps it at. The rest stays
zero, which covers header_len and flit and keeps the Root Error registers
out of the prefix log, where pcie_print_tlp_log() would print them as
end-to-end prefixes.

Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-cxl/20260709165457.8BA181F000E9@smtp.kernel.org/
Fixes: e778ffefa3 ("ACPI: extlog: Trace CPER PCI Express Error Section")
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/20260904172337.1409775-6-dave.jiang@intel.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Dave Jiang 2026-09-04 10:23:29 -07:00 committed by Rafael J. Wysocki
parent 179ef6d7f9
commit 31333d134a

View File

@ -137,7 +137,7 @@ static void extlog_print_pcie(struct cper_sec_pcie *pcie_err,
int severity)
{
#ifdef ACPI_APEI_PCIEAER
struct aer_capability_regs *aer;
struct aer_capability_regs aer_regs = {};
struct pci_dev *pdev;
unsigned int devfn;
unsigned int bus;
@ -149,7 +149,21 @@ static void extlog_print_pcie(struct cper_sec_pcie *pcie_err,
return;
aer_severity = cper_severity_to_aer(severity);
aer = (struct aer_capability_regs *)pcie_err->aer_info;
/*
* struct pcie_tlp_log is larger than the hardware layout, so aer_info
* only maps onto the struct up to the four Header Log DWORDs. Copy that
* much, then place the TLP Prefix Log from where the hardware keeps it.
* Everything else stays zero: nothing reads root_command, root_status or
* the error source IDs, and header_len and flit are software-only.
*/
memcpy(&aer_regs, pcie_err->aer_info,
offsetof(struct aer_capability_regs, header_log) +
PCIE_STD_NUM_TLP_HEADERLOG * sizeof(u32));
memcpy(aer_regs.header_log.prefix,
pcie_err->aer_info + PCI_ERR_PREFIX_LOG,
sizeof(aer_regs.header_log.prefix));
domain = pcie_err->device_id.segment;
bus = pcie_err->device_id.bus;
devfn = PCI_DEVFN(pcie_err->device_id.device,
@ -158,7 +172,7 @@ static void extlog_print_pcie(struct cper_sec_pcie *pcie_err,
if (!pdev)
return;
pci_print_aer(pdev, aer_severity, aer);
pci_print_aer(pdev, aer_severity, &aer_regs);
pci_dev_put(pdev);
#endif
}