Re: [PATCH] ACPI: processor: validate CPU mapping entries

From: Rafael J. Wysocki (Intel)

Date: Mon Nov 09 2026 - 14:12:01 EST


On Sat, Oct 17, 2026 at 9:33 AM jiale yao <19888972804@xxxxxxx> wrote:
>
> At 2026-10-16 22:14:40, "Jiale Yao" <yaojiale02@xxxxxxx> wrote:
> >CPU physical ID lookup walks MADT subtables directly and also accepts
> >records returned by _MAT. Both paths can pass a truncated typed record
> >to a CPU-specific mapper, and the MADT walker can be stalled or moved
> >outside the table by an invalid length.
> >
> >Validate generic record bounds and the minimum size required by each
> >supported CPU record before dispatching it on both provider paths.
> >
>
> Fixes: 78ed8bd2944b ("ACPI: processor: move acpi_get_cpuid into processor_core.c")

So please resend.

Also, is it possible that some systems currently in the field will not
pass this new validation and stop booting as a result?

> >Signed-off-by: Jiale Yao <yaojiale02@xxxxxxx>
> >---
> > drivers/acpi/processor_core.c | 48 ++++++++++++++++++++++++++++++++++-
> > 1 file changed, 47 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
> >index 3bf076c150fa..4d5ff53f27ab 100644
> >--- a/drivers/acpi/processor_core.c
> >+++ b/drivers/acpi/processor_core.c
> >@@ -157,6 +157,47 @@ static int map_core_pic_id(struct acpi_subtable_header *entry,
> > return -EINVAL;
> > }
> >
> >+static bool madt_cpu_entry_is_valid(struct acpi_subtable_header *entry,
> >+ unsigned long end)
> >+{
> >+ unsigned long start = (unsigned long)entry;
> >+ size_t length, min_length;
> >+
> >+ if (start >= end || end - start < sizeof(*entry))
> >+ return false;
> >+
> >+ length = entry->length;
> >+ if (length < sizeof(*entry) || length > end - start)
> >+ return false;
> >+
> >+ switch (entry->type) {
> >+ case ACPI_MADT_TYPE_LOCAL_APIC:
> >+ min_length = sizeof(struct acpi_madt_local_apic);
> >+ break;
> >+ case ACPI_MADT_TYPE_LOCAL_X2APIC:
> >+ min_length = sizeof(struct acpi_madt_local_x2apic);
> >+ break;
> >+ case ACPI_MADT_TYPE_LOCAL_SAPIC:
> >+ min_length = sizeof(struct acpi_madt_local_sapic);
> >+ break;
> >+ case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
> >+ min_length = offsetofend(struct acpi_madt_generic_interrupt,
> >+ arm_mpidr);
> >+ break;
> >+ case ACPI_MADT_TYPE_RINTC:
> >+ min_length = offsetofend(struct acpi_madt_rintc, uid);
> >+ break;
> >+ case ACPI_MADT_TYPE_CORE_PIC:
> >+ min_length = sizeof(struct acpi_madt_core_pic);
> >+ break;
> >+ default:
> >+ min_length = sizeof(*entry);
> >+ break;
> >+ }
> >+
> >+ return length >= min_length;
> >+}
> >+
> > static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
> > int type, u32 acpi_id)
> > {
> >@@ -172,7 +213,8 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
> > /* Parse all entries looking for a match. */
> >
> > entry += sizeof(struct acpi_table_madt);
> >- while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
> >+ while (madt_cpu_entry_is_valid((struct acpi_subtable_header *)entry,
> >+ madt_end)) {
> > struct acpi_subtable_header *header =
> > (struct acpi_subtable_header *)entry;
> > if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
> >@@ -251,6 +293,10 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
> > }
> >
> > header = (struct acpi_subtable_header *)obj->buffer.pointer;
> >+ if (!madt_cpu_entry_is_valid(header,
> >+ (unsigned long)header + obj->buffer.length))
> >+ goto exit;
> >+
> > if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
> > map_lapic_id(header, acpi_id, &phys_id);
> > else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
> >--
> >2.34.1