DF-5432 / fix.diff
diff --git a/sys/platform/pc64/acpica/acpi_madt.c b/sys/platform/pc64/acpica/acpi_madt.c index 0e2b2ac..1111111 100644 --- a/sys/platform/pc64/acpica/acpi_madt.c +++ b/sys/platform/pc64/acpica/acpi_madt.c @@ -44,6 +44,7 @@ #include <machine_base/acpica/acpi_md_cpu.h> #include <machine/specialreg.h> +#include <vm/pmap.h> #include <contrib/dev/acpica/source/include/acpi.h> #include "acpi_sdt_var.h" @@ -572,6 +573,23 @@ struct madt_ioapic_probe_cbarg { int gsi_base0; }; +static boolean_t +madt_ioapic_addr_in_ram(uint32_t addr) +{ + int i; + + /* phys_avail[] holds the available-RAM segments, populated by + * MD boot code long before SI_BOOT2_PRESMP. Device MMIO never + * lives inside them. DF-5432. + */ + for (i = 0; phys_avail[i].phys_end != 0; ++i) { + if (addr >= phys_avail[i].phys_beg && + addr < phys_avail[i].phys_end) + return TRUE; + } + return FALSE; +} + static int madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) { @@ -620,6 +641,19 @@ madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) kprintf("madt_ioapic_probe: zero IOAPIC address\n"); return EINVAL; } + if (madt_ioapic_addr_in_ram(ioapic_ent->Address)) { + /* + * An I/O APIC register file is device MMIO; it + * never lives in system RAM. A MADT claiming + * so is malicious or corrupt -- reject it before + * ioapic_map() hands the page to ioapic_read()/ + * ioapic_write() as a register file. + */ + kprintf("madt_ioapic_probe: IOAPIC address %#x in " + "system RAM, rejecting MADT\n", + ioapic_ent->Address); + return EINVAL; + } if (ioapic_ent->Id == APICID_MAX) { kprintf("madt_ioapic_probe: " "invalid IOAPIC apic id %d\n", |