[PATCH 6/6] platform/x86/intel/pmt: Validate telemetry regions against the BAR

From: David E. Box

Date: Fri Oct 30 2026 - 21:32:01 EST


pmt_resolve_access_pci() computes the base address of a telemetry or
crashlog region from the base offset and BAR index in the device's
discovery header, and the region size also comes from the device. The
resulting range is ioremapped by intel_pmt_dev_register() and can be
mmapped by userspace through sysfs, but it is never checked against the
BAR it claims to be in. A malicious or broken device can therefore
direct the driver at MMIO outside its BAR. For ACCESS_BARID the BAR
index is three bits, so it may also select BAR 6 or 7, which are not
standard BARs.

Check the region against its BAR before it is mapped: the BAR holding the
discovery table for ACCESS_LOCAL, or the BAR named in the header for
ACCESS_BARID.

Fixes: e2729113ce66 ("platform/x86: Intel PMT class driver")
Assisted-by: LLM
Signed-off-by: David E. Box <david.e.box@xxxxxxxxxxxxxxx>
---
drivers/platform/x86/intel/pmt/class.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 2b11c4012f6a..8f87f8db3966 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -214,6 +214,10 @@ static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
struct device *dev = &ivdev->auxdev.dev;
struct intel_pmt_header *header = &entry->header;
struct resource *disc_res;
+ struct resource res;
+ /* BAR the region lives in, the discovery BAR unless the device names one */
+ unsigned int bar = ivdev->tbir;
+ int ret;
u8 bir;

/*
@@ -258,6 +262,7 @@ static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
(disc_res->start <= pci_resource_end(pci_dev, i))) {
entry->base_addr = pci_resource_start(pci_dev, i) +
header->base_offset;
+ bar = i;
break;
}
if (!entry->base_addr)
@@ -280,6 +285,7 @@ static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
*/
entry->base_addr = pci_resource_start(pci_dev, bir) +
GET_ADDRESS(header->base_offset);
+ bar = bir;
break;
default:
dev_err(dev, "Unsupported access type %d\n",
@@ -287,6 +293,20 @@ static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
return -EINVAL;
}

+ /*
+ * The base offset and size come from the device. Make sure the region
+ * lies within the BAR it claims to be in before it is mapped.
+ */
+ if (header->size) {
+ res = DEFINE_RES_MEM(entry->base_addr, header->size);
+
+ ret = intel_vsec_check_bar_resource(ivdev, bar, &res);
+ if (ret) {
+ dev_err(dev, "Region %pR is outside of its BAR\n", &res);
+ return ret;
+ }
+ }
+
return 0;
}

@@ -574,3 +594,4 @@ module_exit(pmt_class_exit);
MODULE_AUTHOR("Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx>");
MODULE_DESCRIPTION("Intel PMT Class driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("INTEL_VSEC");
--
2.43.0