From patchwork Mon Nov 26 11:15:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10698007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CDCF9109C for ; Mon, 26 Nov 2018 11:15:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BEB9928935 for ; Mon, 26 Nov 2018 11:15:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B20D9289C4; Mon, 26 Nov 2018 11:15:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 395E828935 for ; Mon, 26 Nov 2018 11:15:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730279AbeKZWJW (ORCPT ); Mon, 26 Nov 2018 17:09:22 -0500 Received: from mga14.intel.com ([192.55.52.115]:35461 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730325AbeKZWJV (ORCPT ); Mon, 26 Nov 2018 17:09:21 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Nov 2018 03:15:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,281,1539673200"; d="scan'208";a="103207562" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga003.jf.intel.com with ESMTP; 26 Nov 2018 03:15:27 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id CC0251E9; Mon, 26 Nov 2018 13:15:26 +0200 (EET) From: Mika Westerberg To: iommu@lists.linux-foundation.org Cc: Joerg Roedel , David Woodhouse , Lu Baolu , Ashok Raj , Bjorn Helgaas , "Rafael J. Wysocki" , Jacob jun Pan , Andreas Noever , Michael Jamet , Yehezkel Bernat , Lukas Wunner , Christian Kellner , Mario.Limonciello@dell.com, Anthony Wong , Lorenzo Pieralisi , Christoph Hellwig , Alex Williamson , Mika Westerberg , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/4] PCI / ACPI: Identify untrusted PCI devices Date: Mon, 26 Nov 2018 14:15:23 +0300 Message-Id: <20181126111526.56340-2-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181126111526.56340-1-mika.westerberg@linux.intel.com> References: <20181126111526.56340-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Recent systems with Thunderbolt ports may support IOMMU natively. This means that the platform utilizes IOMMU to prevent DMA attacks over externally exposed PCIe root ports (typically Thunderbolt ports) The system BIOS marks these PCIe root ports as being externally facing ports by implementing following ACPI _DSD [1] under the root port in question: Name (_DSD, Package () { ToUUID ("efcc06cc-73ac-4bc3-bff0-76143807c389"), Package () { Package () {"ExternalFacingPort", 1}, Package () {"UID", 0 } } }) To make it possible for IOMMU code to identify these devices, we look up for this property and mark all children devices (including the root port itself) with a new flag (->is_untrusted). This flag is meant to be used with all PCIe devices (not just Thunderbolt) that cannot be trusted in the same level than integrated devices and may need to put behind full IOMMU protection. [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 --- drivers/acpi/property.c | 3 +++ drivers/pci/pci-acpi.c | 18 ++++++++++++++++++ drivers/pci/probe.c | 22 ++++++++++++++++++++++ include/linux/pci.h | 8 ++++++++ 4 files changed, 51 insertions(+) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 8c7c4583b52d..4bdad32f62c8 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -31,6 +31,9 @@ static const guid_t prp_guids[] = { /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */ GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3, 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4), + /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */ + GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3, + 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89), }; static const guid_t ads_guid = diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 921db6f80340..84233cf46fc2 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -789,6 +789,23 @@ 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. + */ + dev->is_untrusted = val == 1; +} + static void pci_acpi_setup(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -798,6 +815,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) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b1c05b5054a0..144623ae2e68 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1378,6 +1378,26 @@ static void set_pcie_thunderbolt(struct pci_dev *dev) } } +static void set_pcie_untrusted(struct pci_dev *dev) +{ + struct pci_dev *parent; + + /* + * Walk up the device hierarchy and check for any upstream bridge + * that has is_untrusted set to true. In that case treat this one + * untrusted as well. + */ + parent = pci_upstream_bridge(dev); + while (parent) { + if (parent->is_untrusted) { + dev->is_untrusted = true; + break; + } + + parent = pci_upstream_bridge(parent); + } +} + /** * pci_ext_cfg_is_aliased - Is ext config space just an alias of std config? * @dev: PCI device @@ -1638,6 +1658,8 @@ int pci_setup_device(struct pci_dev *dev) /* Need to have dev->cfg_size ready */ set_pcie_thunderbolt(dev); + set_pcie_untrusted(dev); + /* "Unknown power state" */ dev->current_state = PCI_UNKNOWN; diff --git a/include/linux/pci.h b/include/linux/pci.h index 11c71c4ecf75..3fa73cc6cf68 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 is_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 */ From patchwork Mon Nov 26 11:15:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10698013 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A49AF109C for ; Mon, 26 Nov 2018 11:16:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 94EE128935 for ; Mon, 26 Nov 2018 11:16:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 878F22893E; Mon, 26 Nov 2018 11:16:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 81C5F28935 for ; Mon, 26 Nov 2018 11:16:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729463AbeKZWJm (ORCPT ); Mon, 26 Nov 2018 17:09:42 -0500 Received: from mga07.intel.com ([134.134.136.100]:4796 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730327AbeKZWJV (ORCPT ); Mon, 26 Nov 2018 17:09:21 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Nov 2018 03:15:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,281,1539673200"; d="scan'208";a="95027118" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga008.jf.intel.com with ESMTP; 26 Nov 2018 03:15:27 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id DE7A632B; Mon, 26 Nov 2018 13:15:26 +0200 (EET) From: Mika Westerberg To: iommu@lists.linux-foundation.org Cc: Joerg Roedel , David Woodhouse , Lu Baolu , Ashok Raj , Bjorn Helgaas , "Rafael J. Wysocki" , Jacob jun Pan , Andreas Noever , Michael Jamet , Yehezkel Bernat , Lukas Wunner , Christian Kellner , Mario.Limonciello@dell.com, Anthony Wong , Lorenzo Pieralisi , Christoph Hellwig , Alex Williamson , Mika Westerberg , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/4] iommu/vt-d: Force IOMMU on for platform opt in hint Date: Mon, 26 Nov 2018 14:15:24 +0300 Message-Id: <20181126111526.56340-3-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181126111526.56340-1-mika.westerberg@linux.intel.com> References: <20181126111526.56340-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Lu Baolu Intel VT-d spec added a new DMA_CTRL_PLATFORM_OPT_IN_FLAG flag in DMAR ACPI table for BIOS to report compliance about platform initiated DMA restricted to RMRR ranges when transferring control to the OS. The OS 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[1] 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 is_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 is_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://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 --- drivers/iommu/dmar.c | 25 +++++++++++++++++ drivers/iommu/intel-iommu.c | 53 +++++++++++++++++++++++++++++++++++-- include/linux/dmar.h | 8 ++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index d9c748b6f9e4..1edf2a251336 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -2042,3 +2042,28 @@ int dmar_device_remove(acpi_handle handle) { return dmar_device_hotplug(handle, false); } + +/* + * dmar_platform_optin - Is %DMA_CTRL_PLATFORM_OPT_IN_FLAG set in DMAR table + * + * Returns true if the platform has %DMA_CTRL_PLATFORM_OPT_IN_FLAG set in + * the ACPI DMAR table. This means that the platform boot firmware has made + * sure no device can issue DMA outside of RMRR regions. + */ +bool dmar_platform_optin(void) +{ + struct acpi_table_dmar *dmar; + acpi_status status; + bool ret; + + status = acpi_get_table(ACPI_SIG_DMAR, 0, + (struct acpi_table_header **)&dmar); + if (ACPI_FAILURE(status)) + return false; + + ret = !!(dmar->flags & DMAR_PLATFORM_OPT_IN); + acpi_put_table((struct acpi_table_header *)dmar); + + return ret; +} +EXPORT_SYMBOL_GPL(dmar_platform_optin); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 41a4b8808802..76e135ee9b19 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -184,6 +184,7 @@ static int rwbf_quirk; */ static int force_on = 0; int intel_iommu_tboot_noforce; +static int no_platform_optin; #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry)) @@ -503,6 +504,7 @@ static int __init intel_iommu_setup(char *str) pr_info("IOMMU enabled\n"); } else if (!strncmp(str, "off", 3)) { dmar_disabled = 1; + no_platform_optin = 1; pr_info("IOMMU disabled\n"); } else if (!strncmp(str, "igfx_off", 8)) { dmar_map_gfx = 0; @@ -2895,6 +2897,13 @@ static int iommu_should_identity_map(struct device *dev, int startup) if (device_is_rmrr_locked(dev)) return 0; + /* + * Prevent any device marked as untrusted from getting + * placed into the statically identity mapping domain. + */ + if (pdev->is_untrusted) + return 0; + if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) return 1; @@ -4728,14 +4737,54 @@ const struct attribute_group *intel_iommu_groups[] = { NULL, }; +static int __init platform_optin_force_iommu(void) +{ + struct pci_dev *pdev = NULL; + bool has_untrusted_dev = false; + + if (!dmar_platform_optin() || no_platform_optin) + return 0; + + for_each_pci_dev(pdev) { + if (pdev->is_untrusted) { + has_untrusted_dev = true; + break; + } + } + + if (!has_untrusted_dev) + return 0; + + if (no_iommu || dmar_disabled) + pr_info("Intel-IOMMU force enabled due to platform opt in\n"); + + /* + * If Intel-IOMMU is disabled by default, we will apply identity + * map for all devices except those marked as being untrusted. + */ + if (dmar_disabled) + iommu_identity_mapping |= IDENTMAP_ALL; + + dmar_disabled = 0; +#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB) + swiotlb = 0; +#endif + no_iommu = 0; + + return 1; +} + int __init intel_iommu_init(void) { int ret = -ENODEV; struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; - /* VT-d is required for a TXT/tboot launch, so enforce that */ - force_on = tboot_force_iommu(); + /* + * Intel IOMMU is required for a TXT/tboot launch or platform + * opt in, so enforce that. + */ + force_on = tboot_force_iommu() || platform_optin_force_iommu(); if (iommu_init_mempool()) { if (force_on) 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 { From patchwork Mon Nov 26 11:15:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10698003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A2414109C for ; Mon, 26 Nov 2018 11:15:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9098A28935 for ; Mon, 26 Nov 2018 11:15:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 83D3C2893E; Mon, 26 Nov 2018 11:15:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFA3928935 for ; Mon, 26 Nov 2018 11:15:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730349AbeKZWJW (ORCPT ); Mon, 26 Nov 2018 17:09:22 -0500 Received: from mga06.intel.com ([134.134.136.31]:13922 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726231AbeKZWJU (ORCPT ); Mon, 26 Nov 2018 17:09:20 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Nov 2018 03:15:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,281,1539673200"; d="scan'208";a="94071696" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga006.jf.intel.com with ESMTP; 26 Nov 2018 03:15:27 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id F0B13546; Mon, 26 Nov 2018 13:15:26 +0200 (EET) From: Mika Westerberg To: iommu@lists.linux-foundation.org Cc: Joerg Roedel , David Woodhouse , Lu Baolu , Ashok Raj , Bjorn Helgaas , "Rafael J. Wysocki" , Jacob jun Pan , Andreas Noever , Michael Jamet , Yehezkel Bernat , Lukas Wunner , Christian Kellner , Mario.Limonciello@dell.com, Anthony Wong , Lorenzo Pieralisi , Christoph Hellwig , Alex Williamson , Mika Westerberg , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/4] iommu/vt-d: Do not enable ATS for untrusted devices Date: Mon, 26 Nov 2018 14:15:25 +0300 Message-Id: <20181126111526.56340-4-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181126111526.56340-1-mika.westerberg@linux.intel.com> References: <20181126111526.56340-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently Linux automatically enables ATS (Address Translation Service) for any device that supports it (and IOMMU is turned on). ATS is used to accelerate DMA access as the device can cache translations locally so there is no need to do full translation on IOMMU side. However, as pointed out in [1] ATS can be used to bypass IOMMU based security completely by simply sending PCIe read/write transaction with AT (Address Translation) field set to "translated". To mitigate this modify the Intel IOMMU code so that it does not enable ATS for any device that is marked as being untrusted. In case this turns out to cause performance issues we may selectively allow ATS based on user decision but currently use big hammer and disable it completely to be on the safe side. [1] https://www.repository.cam.ac.uk/handle/1810/274352 Signed-off-by: Mika Westerberg Reviewed-by: Ashok Raj Reviewed-by: Joerg Roedel Acked-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 76e135ee9b19..c964315deddd 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1473,7 +1473,8 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info) if (info->pri_supported && !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32)) info->pri_enabled = 1; #endif - if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) { + if (!pdev->is_untrusted && info->ats_supported && + !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) { info->ats_enabled = 1; domain_update_iotlb(info->domain); info->ats_qdep = pci_ats_queue_depth(pdev); From patchwork Mon Nov 26 11:15:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 10697999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2B62E13AD for ; Mon, 26 Nov 2018 11:15:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1BB6E28935 for ; Mon, 26 Nov 2018 11:15:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0FE2328A17; Mon, 26 Nov 2018 11:15:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7722F28935 for ; Mon, 26 Nov 2018 11:15:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730027AbeKZWJ2 (ORCPT ); Mon, 26 Nov 2018 17:09:28 -0500 Received: from mga03.intel.com ([134.134.136.65]:44833 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730328AbeKZWJW (ORCPT ); Mon, 26 Nov 2018 17:09:22 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Nov 2018 03:15:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,281,1539673200"; d="scan'208";a="111288271" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 26 Nov 2018 03:15:27 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id 0B0E8591; Mon, 26 Nov 2018 13:15:27 +0200 (EET) From: Mika Westerberg To: iommu@lists.linux-foundation.org Cc: Joerg Roedel , David Woodhouse , Lu Baolu , Ashok Raj , Bjorn Helgaas , "Rafael J. Wysocki" , Jacob jun Pan , Andreas Noever , Michael Jamet , Yehezkel Bernat , Lukas Wunner , Christian Kellner , Mario.Limonciello@dell.com, Anthony Wong , Lorenzo Pieralisi , Christoph Hellwig , Alex Williamson , Mika Westerberg , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/4] thunderbolt: Export IOMMU based DMA protection support to userspace Date: Mon, 26 Nov 2018 14:15:26 +0300 Message-Id: <20181126111526.56340-5-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181126111526.56340-1-mika.westerberg@linux.intel.com> References: <20181126111526.56340-1-mika.westerberg@linux.intel.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Recent systems with Thunderbolt ports may support IOMMU natively. In practice this means that Thunderbolt connected devices are placed behind an IOMMU during the whole time it is connected (including during boot) making Thunderbolt security levels redundant. This is called Kernel DMA protection [1] by Microsoft. Some of these systems still have Thunderbolt security level set to "user" in order to support OS downgrade (the older version of the OS might not support IOMMU based DMA protection so connecting a device still relies on user approval). Export this information to userspace by introducing a new sysfs attribute (iommu_dma_protection). Based on it userspace tools can make more accurate decision whether or not authorize the connected device. In addition update Thunderbolt documentation regarding IOMMU based DMA protection. [1] https://docs.microsoft.com/en-us/windows/security/information-protection/kernel-dma-protection-for-thunderbolt Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat --- .../ABI/testing/sysfs-bus-thunderbolt | 9 +++++++++ Documentation/admin-guide/thunderbolt.rst | 20 +++++++++++++++++++ drivers/thunderbolt/domain.c | 17 ++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt b/Documentation/ABI/testing/sysfs-bus-thunderbolt index 151584a1f950..b21fba14689b 100644 --- a/Documentation/ABI/testing/sysfs-bus-thunderbolt +++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt @@ -21,6 +21,15 @@ Description: Holds a comma separated list of device unique_ids that If a device is authorized automatically during boot its boot attribute is set to 1. +What: /sys/bus/thunderbolt/devices/.../domainX/iommu_dma_protection +Date: Mar 2019 +KernelVersion: 4.21 +Contact: thunderbolt-software@lists.01.org +Description: This attribute tells whether the system uses IOMMU + for DMA protection. Value of 1 means IOMMU is used 0 means + it is not (DMA protection is solely based on Thunderbolt + security levels). + What: /sys/bus/thunderbolt/devices/.../domainX/security Date: Sep 2017 KernelVersion: 4.13 diff --git a/Documentation/admin-guide/thunderbolt.rst b/Documentation/admin-guide/thunderbolt.rst index 35fccba6a9a6..9158d66f04a4 100644 --- a/Documentation/admin-guide/thunderbolt.rst +++ b/Documentation/admin-guide/thunderbolt.rst @@ -133,6 +133,26 @@ If the user still wants to connect the device they can either approve the device without a key or write a new key and write 1 to the ``authorized`` file to get the new key stored on the device NVM. +DMA protection utilizing IOMMU +------------------------------ +Recent systems from 2018 and forward with Thunderbolt ports may natively +support IOMMU. This means that Thunderbolt security is handled by an IOMMU +so connected devices cannot access memory regions outside of what is +allocated for them by drivers. When Linux is running on such system it +automatically enables IOMMU if not enabled by the user already. These +systems can be identified by reading ``1`` from +``/sys/bus/thunderbolt/devices/domainX/iommu_dma_protection`` attribute. + +The driver does not do anything special in this case but because DMA +protection is handled by the IOMMU, security levels (if set) are +redundant. For this reason some systems ship with security level set to +``none``. Other systems have security level set to ``user`` in order to +support downgrade to older OS, so users who want to automatically +authorize devices when IOMMU DMA protection is enabled can use the +following ``udev`` rule:: + + ACTION=="add", SUBSYSTEM=="thunderbolt", ATTRS{iommu_dma_protection}=="1", ATTR{authorized}=="0", ATTR{authorized}="1" + Upgrading NVM on Thunderbolt device or host ------------------------------------------- Since most of the functionality is handled in firmware running on a diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 93e562f18d40..7416bdbd8576 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -7,7 +7,9 @@ */ #include +#include #include +#include #include #include #include @@ -236,6 +238,20 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(boot_acl); +static ssize_t iommu_dma_protection_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /* + * Kernel DMA protection is a feature where Thunderbolt security is + * handled natively using IOMMU. It is enabled when IOMMU is + * enabled and ACPI DMAR table has DMAR_PLATFORM_OPT_IN set. + */ + return sprintf(buf, "%d\n", + iommu_present(&pci_bus_type) && dmar_platform_optin()); +} +static DEVICE_ATTR_RO(iommu_dma_protection); + static ssize_t security_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -251,6 +267,7 @@ static DEVICE_ATTR_RO(security); static struct attribute *domain_attrs[] = { &dev_attr_boot_acl.attr, + &dev_attr_iommu_dma_protection.attr, &dev_attr_security.attr, NULL, };