summaryrefslogtreecommitdiff
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2018-08-16 12:28:48 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2018-12-05 12:01:55 +0300
commit617654aae50eb59dd98aa53fb562e850937f4cde (patch)
tree8daf2232117f9b2c759b6f9ae641eab55c0faacf /drivers/pci/pci-acpi.c
parent2595646791c319cadfdbf271563aac97d0843dc7 (diff)
downloadlinux-617654aae50eb59dd98aa53fb562e850937f4cde.tar.gz
PCI / ACPI: Identify untrusted PCI devices
A malicious PCI device may use DMA to attack the system. An external Thunderbolt port is a convenient point to attach such a device. The OS may use IOMMU to defend against DMA attacks. Some BIOSes mark these externally facing root ports with this ACPI _DSD [1]: Name (_DSD, Package () { ToUUID ("efcc06cc-73ac-4bc3-bff0-76143807c389"), Package () { Package () {"ExternalFacingPort", 1}, Package () {"UID", 0 } } }) If we find such a root port, mark it and all its children as untrusted. The rest of the OS may use this information to enable DMA protection against malicious devices. For instance the device may be put behind an IOMMU to keep it from accessing memory outside of what the driver has allocated for it. While at it, add a comment on top of prp_guids array explaining the possible caveat resulting when these GUIDs are treated equivalent. [1] https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#identifying-externally-exposed-pcie-root-ports Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 921db6f80340..e1949f7efd9c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -789,6 +789,24 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
ACPI_FREE(obj);
}
+static void pci_acpi_set_untrusted(struct pci_dev *dev)
+{
+ u8 val;
+
+ if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+ return;
+ if (device_property_read_u8(&dev->dev, "ExternalFacingPort", &val))
+ return;
+
+ /*
+ * These root ports expose PCIe (including DMA) outside of the
+ * system so make sure we treat them and everything behind as
+ * untrusted.
+ */
+ if (val)
+ dev->untrusted = 1;
+}
+
static void pci_acpi_setup(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -798,6 +816,7 @@ static void pci_acpi_setup(struct device *dev)
return;
pci_acpi_optimize_delay(pci_dev, adev->handle);
+ pci_acpi_set_untrusted(pci_dev);
pci_acpi_add_pm_notifier(adev, pci_dev);
if (!adev->wakeup.flags.valid)