From: Lorenzo Pieralisi lorenzo.pieralisi@arm.com
stable inclusion from stable-4.19.247 commit b322e833697c61a1ee1c239dd4a42b38f6ad531 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5FNPY CVE: NA
--------------------------------
commit 1bbc21785b7336619fb6a67f1fff5afdaf229acc upstream.
Currently the sysfs interface maps the BERT error region as "memory" (through acpi_os_map_memory()) in order to copy the error records into memory buffers through memory operations (eg memory_read_from_buffer()).
The OS system cannot detect whether the BERT error region is part of system RAM or it is "device memory" (eg BMC memory) and therefore it cannot detect which memory attributes the bus to memory support (and corresponding kernel mapping, unless firmware provides the required information).
The acpi_os_map_memory() arch backend implementation determines the mapping attributes. On arm64, if the BERT error region is not present in the EFI memory map, the error region is mapped as device-nGnRnE; this triggers alignment faults since memcpy unaligned accesses are not allowed in device-nGnRnE regions.
The ACPI sysfs code cannot therefore map by default the BERT error region with memory semantics but should use a safer default.
Change the sysfs code to map the BERT error region as MMIO (through acpi_os_map_iomem()) and use the memcpy_fromio() interface to read the error region into the kernel buffer.
Link: https://lore.kernel.org/linux-arm-kernel/31ffe8fc-f5ee-2858-26c5-0fd8bdd6870... Link: https://lore.kernel.org/linux-acpi/CAJZ5v0g+OVbhuUUDrLUCfX_mVqY_e8ubgLTU98=j... Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Tested-by: Veronika Kabatova vkabatov@redhat.com Tested-by: Aristeu Rozanski aris@redhat.com Acked-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com
Conflicts: drivers/acpi/sysfs.c [wangxiongfeng: fix conflicts caused by commit bdd56d7d89 ACPI: sysfs: Make sparse happy about address space in use] Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com Signed-off-by: Laibin Qiu qiulaibin@huawei.com --- drivers/acpi/sysfs.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 0a8eb8961770..f0c64b6837d3 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -439,18 +439,29 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj, { struct acpi_data_attr *data_attr; void __iomem *base; - ssize_t rc; + ssize_t size;
data_attr = container_of(bin_attr, struct acpi_data_attr, attr); + size = data_attr->attr.size; + + if (offset < 0) + return -EINVAL; + + if (offset >= size) + return 0;
- base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size); + if (count > size - offset) + count = size - offset; + + base = acpi_os_map_iomem(data_attr->addr, size); if (!base) return -ENOMEM; - rc = memory_read_from_buffer(buf, count, &offset, base, - data_attr->attr.size); - acpi_os_unmap_memory(base, data_attr->attr.size);
- return rc; + memcpy_fromio(buf, base + offset, count); + + acpi_os_unmap_iomem(base, size); + + return count; }
static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)