Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp1653087pxp; Thu, 17 Mar 2022 13:40:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw5tyuFIKTwQI0v+lDPdvh8maw7tjarIHnpVZojGwbUnr7+z12POaYKpD2Amt0zZTFvcAjB X-Received: by 2002:a17:90b:1d83:b0:1bf:39d7:207d with SMTP id pf3-20020a17090b1d8300b001bf39d7207dmr18155940pjb.130.1647549653806; Thu, 17 Mar 2022 13:40:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647549653; cv=none; d=google.com; s=arc-20160816; b=s2FNd4Ak3zqqkvwlpYXDbkA5xKLvOF4yjAauJ/ay6oIrLN5q5zWqKid+l0mB0MXpcd Z+1cG/zVRSva/K3RLtvz0Pb0kvYbNSRIe8GlUJLThAey8Clz5Kh41uHifWESHxOwXFsQ pWJ66mr4Kf4mieaOzZRLqw8z7midkc7ZYDP+czX4eHuYTNd2jNYB+Mh9x5l7LvUAzQcQ yZ+u2D2xPAkRaUJX3o9rNxGAu9CtwphAr/CUI+3y+i3vVjx+dXQ20zI9HRw3LehPs8Cf A84Vi+aMAlv9N3Z77nnVKAnAQIbiIreRnh3iHXoL+860gjBrk8e5MK2f2Vt7JU/udYAn s9LA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=/zya2QVEWompff+haetmlQGaqtnsT5yysuXc49FXV9M=; b=akciGPaotVSxl4QbZsXy1h/eIpElP2BCam4SusIhBR9TrBPu3U7G2jG9Y2+p8OK6Cz rP7Y0uz+FPnG/X5GLMoz2IXVDTAFtFAhn/VXN1VPnrfrDfIxCGxm7owK+1ekk7Sr5H5w WGMs7RNJKJdA0e3J/NMNidFzoOWtfz/+e92SBeOBdBGrXygl8RT0disFVOKltPsPGsAL I2x+2HRgNonNGf3P2UiJ7qne0cYEyr286g/Le4qGbBtu9mab6yu/6yr+uQzztQ3S4T6m Pn35DM7hsvAdKm0RUeO379oBJpamy/0Fx/OzNyQ1MF5xSkPLHFsAA0mOKiVEerR4qTiv 89rQ== ARC-Authentication-Results: i=1; mx.google.com; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id t1-20020a637801000000b003816043f009si3100361pgc.510.2022.03.17.13.40.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Mar 2022 13:40:53 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id AFA9F29343E; Thu, 17 Mar 2022 13:09:18 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233298AbiCQQSf (ORCPT + 99 others); Thu, 17 Mar 2022 12:18:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42328 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229812AbiCQQSe (ORCPT ); Thu, 17 Mar 2022 12:18:34 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 91E122156CE; Thu, 17 Mar 2022 09:17:17 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 571631424; Thu, 17 Mar 2022 09:17:17 -0700 (PDT) Received: from e121345-lin.cambridge.arm.com (e121345-lin.cambridge.arm.com [10.1.196.40]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 24DC83F7B4; Thu, 17 Mar 2022 09:17:16 -0700 (PDT) From: Robin Murphy To: andreas.noever@gmail.com, michael.jamet@intel.com, mika.westerberg@linux.intel.com, YehezkelShB@gmail.com Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, linux-pci@vger.kernel.org, mario.limonciello@amd.com Subject: [PATCH] thunderbolt: Make iommu_dma_protection more accurate Date: Thu, 17 Mar 2022 16:17:07 +0000 Message-Id: <2d01fa50c2650c730b0244929097737918e302e7.1647533152.git.robin.murphy@arm.com> X-Mailer: git-send-email 2.28.0.dirty MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RDNS_NONE, SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Between me trying to get rid of iommu_present() and Mario wanting to support the AMD equivalent of DMAR_PLATFORM_OPT_IN, scrutiny has shown that the iommu_dma_protection attribute is being far too optimistic. Even if an IOMMU might be present for some PCI segment in the system, that doesn't necessarily mean it provides translation for the device(s) we care about. Furthermore, all that DMAR_PLATFORM_OPT_IN really does is tell us that memory was protected before the kernel was loaded, and prevent the user from disabling the intel-iommu driver entirely. What actually matters is whether we trust individual devices, based on the "external facing" property that we expect firmware to describe for Thunderbolt ports. Avoid false positives by looking as close as possible to the same PCI topology that the IOMMU layer will consider once a Thunderbolt endpoint appears. Crucially, we can't assume that IOMMU translation being enabled for any reason is sufficient on its own; full (expensive) DMA protection will still only be imposed on untrusted devices. CC: Mario Limonciello Signed-off-by: Robin Murphy --- This supersedes my previous attempt just trying to replace iommu_present() at [1], further to the original discussion at [2]. [1] https://lore.kernel.org/linux-iommu/BL1PR12MB515799C0BE396377DBBEF055E2119@BL1PR12MB5157.namprd12.prod.outlook.com/T/ [2] https://lore.kernel.org/linux-iommu/202203160844.lKviWR1Q-lkp@intel.com/T/ drivers/thunderbolt/domain.c | 12 +++--------- drivers/thunderbolt/nhi.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/thunderbolt.h | 2 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 7018d959f775..d5c825e84ac8 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -7,9 +7,7 @@ */ #include -#include #include -#include #include #include #include @@ -257,13 +255,9 @@ 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()); + struct tb *tb = container_of(dev, struct tb, dev); + + return sprintf(buf, "%d\n", tb->nhi->iommu_dma_protection); } static DEVICE_ATTR_RO(iommu_dma_protection); diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index c73da0532be4..e12c2e266741 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1102,6 +1103,39 @@ static void nhi_check_quirks(struct tb_nhi *nhi) nhi->quirks |= QUIRK_AUTO_CLEAR_INT; } +static void nhi_check_iommu(struct tb_nhi *nhi) +{ + struct pci_dev *pdev; + bool port_ok = false; + + /* + * Check for sibling devices that look like they should be our + * tunnelled ports. We can reasonably assume that if an IOMMU is + * managing the bridge it will manage any future devices beyond it + * too. If firmware has described a port as external-facing as + * expected then we can trust the IOMMU layer to enforce isolation; + * otherwise even if translation is enabled for existing devices it + * may potentially be overridden for a future tunnelled endpoint. + */ + for_each_pci_bridge(pdev, nhi->pdev->bus) { + if (!pci_is_pcie(pdev) || + !(pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) + continue; + + if (!device_iommu_mapped(&pdev->dev)) + return; + + if (!pdev->untrusted) { + dev_info(&nhi->pdev->dev, + "Assuming unreliable Kernel DMA protection\n"); + return; + } + port_ok = true; + } + nhi->iommu_dma_protection = port_ok; +} + static int nhi_init_msi(struct tb_nhi *nhi) { struct pci_dev *pdev = nhi->pdev; @@ -1219,6 +1253,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; nhi_check_quirks(nhi); + nhi_check_iommu(nhi); res = nhi_init_msi(nhi); if (res) { diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 124e13cb1469..7a8ad984e651 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -465,6 +465,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) * @msix_ida: Used to allocate MSI-X vectors for rings * @going_away: The host controller device is about to disappear so when * this flag is set, avoid touching the hardware anymore. + * @iommu_dma_protection: An IOMMU will isolate external-facing ports. * @interrupt_work: Work scheduled to handle ring interrupt when no * MSI-X is used. * @hop_count: Number of rings (end point hops) supported by NHI. @@ -479,6 +480,7 @@ struct tb_nhi { struct tb_ring **rx_rings; struct ida msix_ida; bool going_away; + bool iommu_dma_protection; struct work_struct interrupt_work; u32 hop_count; unsigned long quirks; -- 2.28.0.dirty