Merge tag 'chrome-platform-firmware-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux

Pull chrome platform firmware updates from Tzung-Bi Shih:
 "Fixes:
    - Don't map no-map memory regions for CBMEM entries
    - Check bound of coreboot table entries

  Cleanups:
  - Fix typo in docs"

* tag 'chrome-platform-firmware-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
  firmware: coreboot: Validate table bounds
  firmware: coreboot: Skip no-map CBMEM entries
  docs: ABI: testing: Fix typo
This commit is contained in:
Linus Torvalds
2026-08-19 08:49:43 -07:00
2 changed files with 37 additions and 8 deletions

View File

@@ -19,7 +19,7 @@ Description:
/sys/firmware/gsmi/vars:
This directory has the same layout (and
underlying implementation as /sys/firmware/efi/vars.
underlying implementation) as /sys/firmware/efi/vars.
See `Documentation/ABI/*/sysfs-firmware-efi-vars`
for more information on how to interact with
this structure.

View File

@@ -13,8 +13,10 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/device-id/coreboot.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -123,7 +125,7 @@ static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_
ptr_end = ptr + len;
ptr_entry = ptr + header->header_bytes;
for (i = 0; i < header->table_entries; i++) {
for (i = 0; i < header->table_entries; i++, ptr_entry += entry->size) {
if (ptr_entry + sizeof(*entry) > ptr_end)
return -EINVAL;
entry = ptr_entry;
@@ -147,6 +149,26 @@ static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_
switch (device->entry.tag) {
case LB_TAG_CBMEM_ENTRY:
/*
* Skip entries that are not exclusively System RAM or
* Reserved memory.
* On ARM64, no-map regions are filtered out as they are
* IORESOURCE_MEM (see request_standard_resources() in
* arch/arm64/kernel/setup.c).
* On x86, CBMEM often resides in standard reserved regions
* (IORES_DESC_RESERVED).
*/
if (region_intersects(device->cbmem_entry.address,
device->cbmem_entry.entry_size,
IORESOURCE_SYSTEM_RAM,
IORES_DESC_NONE) != REGION_INTERSECTS &&
region_intersects(device->cbmem_entry.address,
device->cbmem_entry.entry_size,
IORESOURCE_MEM,
IORES_DESC_RESERVED) != REGION_INTERSECTS) {
kfree(device);
continue;
}
dev_set_name(&device->dev, "cbmem-%08x",
device->cbmem_entry.id);
break;
@@ -155,8 +177,6 @@ static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_
break;
}
ptr_entry += entry->size;
ret = device_register(&device->dev);
if (ret) {
dev_warn(dev, "failed to register coreboot device: %d\n", ret);
@@ -170,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;
@@ -181,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 */
@@ -189,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);