From 617654aae50eb59dd98aa53fb562e850937f4cde Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 16 Aug 2018 12:28:48 +0300 Subject: 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 Acked-by: Rafael J. Wysocki Acked-by: Bjorn Helgaas --- include/linux/pci.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 11c71c4ecf75..c786a2f27bee 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -396,6 +396,14 @@ struct pci_dev { unsigned int is_hotplug_bridge:1; unsigned int shpc_managed:1; /* SHPC owned by shpchp */ unsigned int is_thunderbolt:1; /* Thunderbolt controller */ + /* + * Devices marked being untrusted are the ones that can potentially + * execute DMA attacks and similar. They are typically connected + * through external ports such as Thunderbolt but not limited to + * that. When an IOMMU is enabled they should be getting full + * mappings to make sure they cannot access arbitrary memory. + */ + unsigned int untrusted:1; unsigned int __aer_firmware_first_valid:1; unsigned int __aer_firmware_first:1; unsigned int broken_intx_masking:1; /* INTx masking can't be used */ -- cgit v1.2.3 From 89a6079df791aeace2044ea93be1b397195824ec Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Tue, 23 Oct 2018 15:45:01 +0800 Subject: iommu/vt-d: Force IOMMU on for platform opt in hint Intel VT-d spec added a new DMA_CTRL_PLATFORM_OPT_IN_FLAG flag in DMAR ACPI table [1] for BIOS to report compliance about platform initiated DMA restricted to RMRR ranges when transferring control to the OS. This means that during OS boot, before it enables IOMMU none of the connected devices can bypass DMA protection for instance by overwriting the data structures used by the IOMMU. The OS also treats this as a hint that the IOMMU should be enabled to prevent DMA attacks from possible malicious devices. A use of this flag is Kernel DMA protection for Thunderbolt [2] which in practice means that IOMMU should be enabled for PCIe devices connected to the Thunderbolt ports. With IOMMU enabled for these devices, all DMA operations are limited in the range reserved for it, thus the DMA attacks are prevented. All these devices are enumerated in the PCI/PCIe module and marked with an untrusted flag. This forces IOMMU to be enabled if DMA_CTRL_PLATFORM_OPT_IN_FLAG is set in DMAR ACPI table and there are PCIe devices marked as untrusted in the system. This can be turned off by adding "intel_iommu=off" in the kernel command line, if any problems are found. [1] https://software.intel.com/sites/default/files/managed/c5/15/vt-directed-io-spec.pdf [2] https://docs.microsoft.com/en-us/windows/security/information-protection/kernel-dma-protection-for-thunderbolt Cc: Jacob Pan Cc: Sohil Mehta Signed-off-by: Lu Baolu Signed-off-by: Mika Westerberg Reviewed-by: Ashok Raj Reviewed-by: Joerg Roedel Acked-by: Joerg Roedel --- include/linux/dmar.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 843a41ba7e28..f8af1d770520 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -39,6 +39,7 @@ struct acpi_dmar_header; /* DMAR Flags */ #define DMAR_INTR_REMAP 0x1 #define DMAR_X2APIC_OPT_OUT 0x2 +#define DMAR_PLATFORM_OPT_IN 0x4 struct intel_iommu; @@ -170,6 +171,8 @@ static inline int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert) { return 0; } #endif /* CONFIG_IRQ_REMAP */ +extern bool dmar_platform_optin(void); + #else /* CONFIG_DMAR_TABLE */ static inline int dmar_device_add(void *handle) @@ -182,6 +185,11 @@ static inline int dmar_device_remove(void *handle) return 0; } +static inline bool dmar_platform_optin(void) +{ + return false; +} + #endif /* CONFIG_DMAR_TABLE */ struct irte { -- cgit v1.2.3