mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
firmware: coreboot: Validate table bounds
The existing coreboot_table_populate() bounds checks limit individual
entries to the mapped length. However, coreboot_table_probe() replaces
the platform resource length with header and table sizes supplied by
firmware before mapping the full table.
A malformed table can overflow the 32-bit size addition or advertise an
extent beyond the resource, causing the driver to map and parse memory
outside the resource. A resource shorter than the fixed header is also
mapped as though it contained a complete header.
Reject resources shorter than the fixed header. After validating the
signature, require a complete header, calculate the advertised extent
with overflow checking, and reject extents beyond the resource before
remapping the table.
Fixes: d384d6f43d ("firmware: google memconsole: Add coreboot support")
Signed-off-by: Laxman Acharya Padhya <acharyalaxman8848@gmail.com>
Link: https://lore.kernel.org/r/20260801165651.42172-1-acharyalaxman8848@gmail.com
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
This commit is contained in:
committed by
Tzung-Bi Shih
parent
e31ecda9e3
commit
a58a57a107
@@ -190,6 +190,7 @@ static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_
|
||||
static int coreboot_table_probe(struct platform_device *pdev)
|
||||
{
|
||||
resource_size_t len;
|
||||
resource_size_t table_span;
|
||||
struct coreboot_table_header *header;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -201,7 +202,7 @@ static int coreboot_table_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
|
||||
len = resource_size(res);
|
||||
if (!res->start || !len)
|
||||
if (!res->start || len < sizeof(*header))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check just the header first to make sure things are sane */
|
||||
@@ -209,19 +210,27 @@ static int coreboot_table_probe(struct platform_device *pdev)
|
||||
if (!header)
|
||||
return -ENOMEM;
|
||||
|
||||
len = header->header_bytes + header->table_bytes;
|
||||
ret = strncmp(header->signature, "LBIO", sizeof(header->signature));
|
||||
|
||||
if (!ret &&
|
||||
(header->header_bytes < sizeof(*header) ||
|
||||
check_add_overflow((resource_size_t)header->header_bytes,
|
||||
(resource_size_t)header->table_bytes,
|
||||
&table_span) ||
|
||||
table_span > len))
|
||||
ret = -EINVAL;
|
||||
|
||||
memunmap(header);
|
||||
if (ret) {
|
||||
dev_warn(dev, "coreboot table missing or corrupt!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ptr = memremap(res->start, len, MEMREMAP_WB);
|
||||
ptr = memremap(res->start, table_span, MEMREMAP_WB);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = coreboot_table_populate(dev, ptr, len);
|
||||
ret = coreboot_table_populate(dev, ptr, table_span);
|
||||
|
||||
memunmap(ptr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user