diff options
| author | Titouan Ameline de Cadeville <titouan.ameline@gmail.com> | 2026-04-26 23:47:39 +0200 |
|---|---|---|
| committer | Tzung-Bi Shih <tzungbi@kernel.org> | 2026-04-28 02:30:10 +0000 |
| commit | 7b1a1af4556a4f95ef273e91435fe804cbfcd223 (patch) | |
| tree | 1d1fee8419db775468293aff6dbe8f8ecd6044ad /drivers | |
| parent | 254f49634ee16a731174d2ae34bc50bd5f45e731 (diff) | |
| download | linux-7b1a1af4556a4f95ef273e91435fe804cbfcd223.tar.gz linux-7b1a1af4556a4f95ef273e91435fe804cbfcd223.zip | |
firmware: google: Add bounds checks in coreboot_table_populate()
coreboot_table_populate() iterates over firmware-provided table entries
with no validation that the entries stay within the mapped memory
region. A corrupt table with a large `entry->size` advances `ptr_entry`
past the mapped region, causing an out-of-bounds read on the next
iteration.
Add a check before dereferencing `ptr_entry` to ensure the entry header
is readable, and a second check after reading `entry->size` to ensure
the full entry stays within the mapped region.
Pass `len` from coreboot_table_probe() into coreboot_table_populate() to
make the mapped region size available for validation.
Signed-off-by: Titouan Ameline de Cadeville <titouan.ameline@gmail.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Link: https://lore.kernel.org/r/20260426214739.117131-1-titouan.ameline@gmail.com
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/firmware/google/coreboot_table.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index c769631ea15d..233939e548b4 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -112,16 +112,20 @@ void coreboot_driver_unregister(struct coreboot_driver *driver) } EXPORT_SYMBOL(coreboot_driver_unregister); -static int coreboot_table_populate(struct device *dev, void *ptr) +static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_t len) { int i, ret; void *ptr_entry; struct coreboot_device *device; struct coreboot_table_entry *entry; struct coreboot_table_header *header = ptr; + void *ptr_end; + ptr_end = ptr + len; ptr_entry = ptr + header->header_bytes; for (i = 0; i < header->table_entries; i++) { + if (ptr_entry + sizeof(*entry) > ptr_end) + return -EINVAL; entry = ptr_entry; if (entry->size < sizeof(*entry)) { @@ -129,6 +133,9 @@ static int coreboot_table_populate(struct device *dev, void *ptr) return -EINVAL; } + if (ptr_entry + entry->size > ptr_end) + return -EINVAL; + device = kzalloc(sizeof(device->dev) + entry->size, GFP_KERNEL); if (!device) return -ENOMEM; @@ -194,7 +201,7 @@ static int coreboot_table_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM; - ret = coreboot_table_populate(dev, ptr); + ret = coreboot_table_populate(dev, ptr, len); memunmap(ptr); |
