DF-5483 / fix.diff
--- sys/platform/pc64/acpica/acpi_pstate_machdep.c +++ sys/platform/pc64/acpica/acpi_pstate_machdep.c @@ -487,6 +487,24 @@ acpi_pst_intel_check_csr(const struct acp case ACPI_ADR_SPACE_SYSTEM_IO: if (ctrl->pr_res == NULL) { kprintf("cpu%d: ioport allocation failed for control " "register\n", mycpuid); return ENXIO; } + /* + * The IO port came from firmware (_PCT). A GAS address + * beyond the 16-bit IO space cannot be a port: the x86 + * accessors silently truncate such an "address", so a + * bogus table would make the kernel write to an entirely + * different (truncated) port. Reject it explicitly. + */ + if (ctrl->pr_gas.Address >= 0x10000 || + ctrl->pr_gas.BitWidth / NBBY > 0x10000 - ctrl->pr_gas.Address) { + kprintf("cpu%d: control register IO address %#jx " + "out of range\n", mycpuid, + (uintmax_t)ctrl->pr_gas.Address); + return EINVAL; + } error = acpi_pst_md_gas_verify(&ctrl->pr_gas); if (error) { kprintf("cpu%d: Invalid control register GAS\n", mycpuid); return error; @@ -500,6 +518,16 @@ acpi_pst_intel_check_csr(const struct acp if (status->pr_res == NULL) { kprintf("cpu%d: ioport allocation failed for status " "register\n", mycpuid); return ENXIO; } + if (status->pr_gas.Address >= 0x10000 || + status->pr_gas.BitWidth / NBBY > 0x10000 - status->pr_gas.Address) { + kprintf("cpu%d: status register IO address %#jx " + "out of range\n", mycpuid, + (uintmax_t)status->pr_gas.Address); + return EINVAL; + } error = acpi_pst_md_gas_verify(&status->pr_gas); if (error) { kprintf("cpu%d: Invalid status register GAS\n", mycpuid); |