mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ACPI: sysfs: Map only the requested range in acpi_data_show()
acpi_data_show() maps the whole data region on every read(), although it copies at most count bytes and sysfs passes at most PAGE_SIZE bytes per call. acpi_os_unmap_iomem() defers the iounmap until after an RCU grace period, so a process reading one of these files in a loop keeps many full-size mappings in flight. Map only the range being read. acpi_os_map_iomem() rounds the mapping to page boundaries, so each mapping is now at most two pages, whatever the size of the region. A malformed table can describe a region that wraps around the end of the physical address space. acpi_os_map_iomem() doesn't check for that, and its lookup of existing mappings then matches an unrelated mapping, with or without this change. Fail reads of such a region before mapping anything. Signed-off-by: Jamie Nguyen <jamien@nvidia.com> Link: https://patch.msgid.link/20261013180728.957618-1-jamien@nvidia.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
68a385dbe0
commit
4d23d84ef2
|
|
@ -420,6 +420,7 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
|
|||
struct acpi_data_attr *data_attr;
|
||||
void __iomem *base;
|
||||
ssize_t size;
|
||||
u64 end;
|
||||
|
||||
data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
|
||||
size = data_attr->attr.size;
|
||||
|
|
@ -433,13 +434,17 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
|
|||
if (count > size - offset)
|
||||
count = size - offset;
|
||||
|
||||
base = acpi_os_map_iomem(data_attr->addr, size);
|
||||
/* acpi_os_map_iomem() can't handle a range that wraps around */
|
||||
if (check_add_overflow(data_attr->addr, size, &end))
|
||||
return -EINVAL;
|
||||
|
||||
base = acpi_os_map_iomem(data_attr->addr + offset, count);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy_fromio(buf, base + offset, count);
|
||||
memcpy_fromio(buf, base, count);
|
||||
|
||||
acpi_os_unmap_iomem(base, size);
|
||||
acpi_os_unmap_iomem(base, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user