CVE-2025-40181
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
12/11/2025
Last modified:
12/11/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
x86/kvm: Force legacy PCI hole to UC when overriding MTRRs for TDX/SNP<br />
<br />
When running as an SNP or TDX guest under KVM, force the legacy PCI hole,<br />
i.e. memory between Top of Lower Usable DRAM and 4GiB, to be mapped as UC<br />
via a forced variable MTRR range.<br />
<br />
In most KVM-based setups, legacy devices such as the HPET and TPM are<br />
enumerated via ACPI. ACPI enumeration includes a Memory32Fixed entry, and<br />
optionally a SystemMemory descriptor for an OperationRegion, e.g. if the<br />
device needs to be accessed via a Control Method.<br />
<br />
If a SystemMemory entry is present, then the kernel&#39;s ACPI driver will<br />
auto-ioremap the region so that it can be accessed at will. However, the<br />
ACPI spec doesn&#39;t provide a way to enumerate the memory type of<br />
SystemMemory regions, i.e. there&#39;s no way to tell software that a region<br />
must be mapped as UC vs. WB, etc. As a result, Linux&#39;s ACPI driver always<br />
maps SystemMemory regions using ioremap_cache(), i.e. as WB on x86.<br />
<br />
The dedicated device drivers however, e.g. the HPET driver and TPM driver,<br />
want to map their associated memory as UC or WC, as accessing PCI devices<br />
using WB is unsupported.<br />
<br />
On bare metal and non-CoCO, the conflicting requirements "work" as firmware<br />
configures the PCI hole (and other device memory) to be UC in the MTRRs.<br />
So even though the ACPI mappings request WB, they are forced to UC- in the<br />
kernel&#39;s tracking due to the kernel properly handling the MTRR overrides,<br />
and thus are compatible with the drivers&#39; requested WC/UC-.<br />
<br />
With force WB MTRRs on SNP and TDX guests, the ACPI mappings get their<br />
requested WB if the ACPI mappings are established before the dedicated<br />
driver code attempts to initialize the device. E.g. if acpi_init()<br />
runs before the corresponding device driver is probed, ACPI&#39;s WB mapping<br />
will "win", and result in the driver&#39;s ioremap() failing because the<br />
existing WB mapping isn&#39;t compatible with the requested WC/UC-.<br />
<br />
E.g. when a TPM is emulated by the hypervisor (ignoring the security<br />
implications of relying on what is allegedly an untrusted entity to store<br />
measurements), the TPM driver will request UC and fail:<br />
<br />
[ 1.730459] ioremap error for 0xfed40000-0xfed45000, requested 0x2, got 0x0<br />
[ 1.732780] tpm_tis MSFT0101:00: probe with driver tpm_tis failed with error -12<br />
<br />
Note, the &#39;0x2&#39; and &#39;0x0&#39; values refer to "enum page_cache_mode", not x86&#39;s<br />
memtypes (which frustratingly are an almost pure inversion; 2 == WB, 0 == UC).<br />
E.g. tracing mapping requests for TPM TIS yields:<br />
<br />
Mapping TPM TIS with req_type = 0<br />
WARNING: CPU: 22 PID: 1 at arch/x86/mm/pat/memtype.c:530 memtype_reserve+0x2ab/0x460<br />
Modules linked in:<br />
CPU: 22 UID: 0 PID: 1 Comm: swapper/0 Tainted: G W 6.16.0-rc7+ #2 VOLUNTARY<br />
Tainted: [W]=WARN<br />
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/29/2025<br />
RIP: 0010:memtype_reserve+0x2ab/0x460<br />
__ioremap_caller+0x16d/0x3d0<br />
ioremap_cache+0x17/0x30<br />
x86_acpi_os_ioremap+0xe/0x20<br />
acpi_os_map_iomem+0x1f3/0x240<br />
acpi_os_map_memory+0xe/0x20<br />
acpi_ex_system_memory_space_handler+0x273/0x440<br />
acpi_ev_address_space_dispatch+0x176/0x4c0<br />
acpi_ex_access_region+0x2ad/0x530<br />
acpi_ex_field_datum_io+0xa2/0x4f0<br />
acpi_ex_extract_from_field+0x296/0x3e0<br />
acpi_ex_read_data_from_field+0xd1/0x460<br />
acpi_ex_resolve_node_to_value+0x2ee/0x530<br />
acpi_ex_resolve_to_value+0x1f2/0x540<br />
acpi_ds_evaluate_name_path+0x11b/0x190<br />
acpi_ds_exec_end_op+0x456/0x960<br />
acpi_ps_parse_loop+0x27a/0xa50<br />
acpi_ps_parse_aml+0x226/0x600<br />
acpi_ps_execute_method+0x172/0x3e0<br />
acpi_ns_evaluate+0x175/0x5f0<br />
acpi_evaluate_object+0x213/0x490<br />
acpi_evaluate_integer+0x6d/0x140<br />
acpi_bus_get_status+0x93/0x150<br />
acpi_add_single_object+0x43a/0x7c0<br />
acpi_bus_check_add+0x149/0x3a0<br />
acpi_bus_check_add_1+0x16/0x30<br />
acpi_ns_walk_namespace+0x22c/0x360<br />
acpi_walk_namespace+0x15c/0x170<br />
acpi_bus_scan+0x1dd/0x200<br />
acpi_scan_init+0xe5/0x2b0<br />
acpi_init+0x264/0x5b0<br />
do_one_i<br />
---truncated---



