All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-18 17:42 ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, linux-kernel, mario.limonciello, hch

OK, here's chapter 3 in the story of "but I really just want to
remove iommu_present()", which is the second go at this approach
on the Thunderbolt end, but now improving the IOMMU end as well
since the subtlety of why that still matters has been clarified.
Previous thread here:

https://lore.kernel.org/linux-iommu/f887686a-e7e4-f031-97e8-dbeb1c088095@arm.com/T/

Thanks,
Robin.


Robin Murphy (2):
  iommu: Add capability for pre-boot DMA protection
  thunderbolt: Make iommu_dma_protection more accurate

 drivers/iommu/intel/iommu.c  |  2 ++
 drivers/thunderbolt/domain.c | 12 +++--------
 drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h        |  7 ++++++
 include/linux/thunderbolt.h  |  2 ++
 5 files changed, 55 insertions(+), 9 deletions(-)

-- 
2.28.0.dirty


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 0/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-18 17:42 ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, hch, linux-kernel, mario.limonciello

OK, here's chapter 3 in the story of "but I really just want to
remove iommu_present()", which is the second go at this approach
on the Thunderbolt end, but now improving the IOMMU end as well
since the subtlety of why that still matters has been clarified.
Previous thread here:

https://lore.kernel.org/linux-iommu/f887686a-e7e4-f031-97e8-dbeb1c088095@arm.com/T/

Thanks,
Robin.


Robin Murphy (2):
  iommu: Add capability for pre-boot DMA protection
  thunderbolt: Make iommu_dma_protection more accurate

 drivers/iommu/intel/iommu.c  |  2 ++
 drivers/thunderbolt/domain.c | 12 +++--------
 drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h        |  7 ++++++
 include/linux/thunderbolt.h  |  2 ++
 5 files changed, 55 insertions(+), 9 deletions(-)

-- 
2.28.0.dirty

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
  2022-03-18 17:42 ` Robin Murphy
@ 2022-03-18 17:42   ` Robin Murphy
  -1 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, linux-kernel, mario.limonciello, hch

VT-d's dmar_platform_optin() actually represents a combination of
properties fairly well standardised by Microsoft as "Pre-boot DMA
Protection" and "Kernel DMA Protection"[1]. As such, we can provide
interested consumers with an abstracted capability rather than
driver-specific interfaces that won't scale. We name it for the former
aspect since that's what external callers are most likely to be
interested in; the latter is for the IOMMU layer to handle itself.

Also use this as an opportunity to draw a line in the sand and add a
new interface so as not to introduce any more callers of iommu_capable()
which I also want to get rid of. For now it's a quick'n'dirty wrapper
function, but will evolve to subsume the internal interface in future.

[1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection

Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: New patch

 drivers/iommu/intel/iommu.c | 2 ++
 include/linux/iommu.h       | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0c7975848972..20d8e1f60068 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4817,6 +4817,8 @@ static bool intel_iommu_capable(enum iommu_cap cap)
 		return domain_update_iommu_snooping(NULL);
 	if (cap == IOMMU_CAP_INTR_REMAP)
 		return irq_remapping_enabled == 1;
+	if (cap == IOMMU_CAP_PRE_BOOT_PROTECTION)
+		return dmar_platform_optin();
 
 	return false;
 }
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 4a25f8241207..e16d54e15fee 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -107,6 +107,8 @@ enum iommu_cap {
 					   transactions */
 	IOMMU_CAP_INTR_REMAP,		/* IOMMU supports interrupt isolation */
 	IOMMU_CAP_NOEXEC,		/* IOMMU_NOEXEC flag */
+	IOMMU_CAP_PRE_BOOT_PROTECTION,	/* Firmware says it used the IOMMU for
+					   DMA protection and we should too */
 };
 
 /* These are the possible reserved region types */
@@ -1042,6 +1044,11 @@ static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
 	return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot);
 }
 
+static inline bool dev_iommu_capable(struct device *dev, enum iommu_cap cap)
+{
+	return device_iommu_mapped(dev) && iommu_capable(dev->bus, cap);
+}
+
 #ifdef CONFIG_IOMMU_DEBUGFS
 extern	struct dentry *iommu_debugfs_dir;
 void iommu_debugfs_setup(void);
-- 
2.28.0.dirty


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
@ 2022-03-18 17:42   ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, hch, linux-kernel, mario.limonciello

VT-d's dmar_platform_optin() actually represents a combination of
properties fairly well standardised by Microsoft as "Pre-boot DMA
Protection" and "Kernel DMA Protection"[1]. As such, we can provide
interested consumers with an abstracted capability rather than
driver-specific interfaces that won't scale. We name it for the former
aspect since that's what external callers are most likely to be
interested in; the latter is for the IOMMU layer to handle itself.

Also use this as an opportunity to draw a line in the sand and add a
new interface so as not to introduce any more callers of iommu_capable()
which I also want to get rid of. For now it's a quick'n'dirty wrapper
function, but will evolve to subsume the internal interface in future.

[1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection

Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: New patch

 drivers/iommu/intel/iommu.c | 2 ++
 include/linux/iommu.h       | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0c7975848972..20d8e1f60068 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4817,6 +4817,8 @@ static bool intel_iommu_capable(enum iommu_cap cap)
 		return domain_update_iommu_snooping(NULL);
 	if (cap == IOMMU_CAP_INTR_REMAP)
 		return irq_remapping_enabled == 1;
+	if (cap == IOMMU_CAP_PRE_BOOT_PROTECTION)
+		return dmar_platform_optin();
 
 	return false;
 }
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 4a25f8241207..e16d54e15fee 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -107,6 +107,8 @@ enum iommu_cap {
 					   transactions */
 	IOMMU_CAP_INTR_REMAP,		/* IOMMU supports interrupt isolation */
 	IOMMU_CAP_NOEXEC,		/* IOMMU_NOEXEC flag */
+	IOMMU_CAP_PRE_BOOT_PROTECTION,	/* Firmware says it used the IOMMU for
+					   DMA protection and we should too */
 };
 
 /* These are the possible reserved region types */
@@ -1042,6 +1044,11 @@ static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
 	return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot);
 }
 
+static inline bool dev_iommu_capable(struct device *dev, enum iommu_cap cap)
+{
+	return device_iommu_mapped(dev) && iommu_capable(dev->bus, cap);
+}
+
 #ifdef CONFIG_IOMMU_DEBUGFS
 extern	struct dentry *iommu_debugfs_dir;
 void iommu_debugfs_setup(void);
-- 
2.28.0.dirty

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-18 17:42 ` Robin Murphy
@ 2022-03-18 17:42   ` Robin Murphy
  -1 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, linux-kernel, mario.limonciello, hch

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. While
that lets us assume kernel integrity, what matters for actual runtime
DMA protection is whether we trust individual devices, based on the
"external facing" property that we expect firmware to describe for
Thunderbolt ports.

It's proven challenging to determine the appropriate ports accurately
given the variety of possible topologies, so while still not getting a
perfect answer, by putting enough faith in firmware we can at least get
a good bit closer. If we can see that any device near a Thunderbolt NHI
has all the requisites for Kernel DMA Protection, chances are that it
*is* a relevant port, but moreover that implies that firmware is playing
the game overall, so we'll use that to assume that all Thunderbolt ports
should be correctly marked and thus will end up fully protected.

CC: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Give up trying to look for specific devices, just look for evidence
    that firmware cares at all.

 drivers/thunderbolt/domain.c | 12 +++--------
 drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
 include/linux/thunderbolt.h  |  2 ++
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index 7018d959f775..2889a214dadc 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -7,9 +7,7 @@
  */
 
 #include <linux/device.h>
-#include <linux/dmar.h>
 #include <linux/idr.h>
-#include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
@@ -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 sysfs_emit(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..9e396e283792 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/property.h>
@@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
 		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
 }
 
+static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
+{
+	if (!pdev->untrusted ||
+	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))
+		return 0;
+	*(bool *)data = true;
+	return 1; /* Stop walking */
+}
+
+static void nhi_check_iommu(struct tb_nhi *nhi)
+{
+	struct pci_bus *bus = nhi->pdev->bus;
+	bool port_ok = false;
+
+	/*
+	 * Ideally what we'd do here is grab every PCI device that
+	 * represents a tunnelling adapter for this NHI and check their
+	 * status directly, but unfortunately USB4 seems to make it
+	 * obnoxiously difficult to reliably make any correlation.
+	 *
+	 * So for now we'll have to bodge it... Hoping that the system
+	 * is at least sane enough that an adapter is in the same PCI
+	 * segment as its NHI, if we can find *something* on that segment
+	 * which meets the requirements for Kernel DMA Protection, we'll
+	 * take that to imply that firmware is aware and has (hopefully)
+	 * done the right thing in general. We need to know that the PCI
+	 * layer has seen the ExternalFacingPort property and propagated
+	 * it to the "untrusted" flag that the IOMMU layer will then
+	 * enforce, but also that the IOMMU driver itself can be trusted
+	 * not to have been subverted by a pre-boot DMA attack.
+	 */
+	while (bus->parent)
+		bus = bus->parent;
+
+	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
+
+	nhi->iommu_dma_protection = port_ok;
+}
+
 static int nhi_init_msi(struct tb_nhi *nhi)
 {
 	struct pci_dev *pdev = nhi->pdev;
@@ -1219,6 +1259,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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-18 17:42   ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-18 17:42 UTC (permalink / raw)
  To: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB
  Cc: iommu, linux-usb, hch, linux-kernel, mario.limonciello

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. While
that lets us assume kernel integrity, what matters for actual runtime
DMA protection is whether we trust individual devices, based on the
"external facing" property that we expect firmware to describe for
Thunderbolt ports.

It's proven challenging to determine the appropriate ports accurately
given the variety of possible topologies, so while still not getting a
perfect answer, by putting enough faith in firmware we can at least get
a good bit closer. If we can see that any device near a Thunderbolt NHI
has all the requisites for Kernel DMA Protection, chances are that it
*is* a relevant port, but moreover that implies that firmware is playing
the game overall, so we'll use that to assume that all Thunderbolt ports
should be correctly marked and thus will end up fully protected.

CC: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Give up trying to look for specific devices, just look for evidence
    that firmware cares at all.

 drivers/thunderbolt/domain.c | 12 +++--------
 drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
 include/linux/thunderbolt.h  |  2 ++
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index 7018d959f775..2889a214dadc 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -7,9 +7,7 @@
  */
 
 #include <linux/device.h>
-#include <linux/dmar.h>
 #include <linux/idr.h>
-#include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
@@ -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 sysfs_emit(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..9e396e283792 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/property.h>
@@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
 		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
 }
 
+static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
+{
+	if (!pdev->untrusted ||
+	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))
+		return 0;
+	*(bool *)data = true;
+	return 1; /* Stop walking */
+}
+
+static void nhi_check_iommu(struct tb_nhi *nhi)
+{
+	struct pci_bus *bus = nhi->pdev->bus;
+	bool port_ok = false;
+
+	/*
+	 * Ideally what we'd do here is grab every PCI device that
+	 * represents a tunnelling adapter for this NHI and check their
+	 * status directly, but unfortunately USB4 seems to make it
+	 * obnoxiously difficult to reliably make any correlation.
+	 *
+	 * So for now we'll have to bodge it... Hoping that the system
+	 * is at least sane enough that an adapter is in the same PCI
+	 * segment as its NHI, if we can find *something* on that segment
+	 * which meets the requirements for Kernel DMA Protection, we'll
+	 * take that to imply that firmware is aware and has (hopefully)
+	 * done the right thing in general. We need to know that the PCI
+	 * layer has seen the ExternalFacingPort property and propagated
+	 * it to the "untrusted" flag that the IOMMU layer will then
+	 * enforce, but also that the IOMMU driver itself can be trusted
+	 * not to have been subverted by a pre-boot DMA attack.
+	 */
+	while (bus->parent)
+		bus = bus->parent;
+
+	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
+
+	nhi->iommu_dma_protection = port_ok;
+}
+
 static int nhi_init_msi(struct tb_nhi *nhi)
 {
 	struct pci_dev *pdev = nhi->pdev;
@@ -1219,6 +1259,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

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* RE: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-18 17:42   ` Robin Murphy
@ 2022-03-18 22:29     ` Limonciello, Mario via iommu
  -1 siblings, 0 replies; 24+ messages in thread
From: Limonciello, Mario @ 2022-03-18 22:29 UTC (permalink / raw)
  To: Robin Murphy, joro, baolu.lu, andreas.noever, michael.jamet,
	mika.westerberg, YehezkelShB
  Cc: iommu, linux-usb, linux-kernel, hch

[Public]

> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 

This approach looks generally good to me.  I do worry a little bit about older
systems that didn't set ExternalFacingPort in the FW but were previously setting
iommu_dma_protection, but I think that those could be treated on a quirk
basis to set PCI IDs for those root ports as external facing if/when they come
up.

I'll send up a follow up patch that adds the AMD ACPI table check.
If it looks good can roll it into your series for v3, or if this series goes
as is for v2 it can come on its own.

> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: Give up trying to look for specific devices, just look for evidence
>     that firmware cares at all.

I still do think you could know exactly which devices to use if you're in
SW CM mode, but I guess the consensus is to not bifurcate the way this
can be checked.

> 
>  drivers/thunderbolt/domain.c | 12 +++--------
>  drivers/thunderbolt/nhi.c    | 41
> ++++++++++++++++++++++++++++++++++++
>  include/linux/thunderbolt.h  |  2 ++
>  3 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
> index 7018d959f775..2889a214dadc 100644
> --- a/drivers/thunderbolt/domain.c
> +++ b/drivers/thunderbolt/domain.c
> @@ -7,9 +7,7 @@
>   */
> 
>  #include <linux/device.h>
> -#include <linux/dmar.h>
>  #include <linux/idr.h>
> -#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
> @@ -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 sysfs_emit(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..9e396e283792 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -14,6 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/pci.h>
>  #include <linux/interrupt.h>
> +#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/delay.h>
>  #include <linux/property.h>
> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>  		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>  }
> 
> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
> +{
> +	if (!pdev->untrusted ||
> +	    !dev_iommu_capable(&pdev->dev,
> IOMMU_CAP_PRE_BOOT_PROTECTION))
> +		return 0;
> +	*(bool *)data = true;
> +	return 1; /* Stop walking */
> +}
> +
> +static void nhi_check_iommu(struct tb_nhi *nhi)
> +{
> +	struct pci_bus *bus = nhi->pdev->bus;
> +	bool port_ok = false;
> +
> +	/*
> +	 * Ideally what we'd do here is grab every PCI device that
> +	 * represents a tunnelling adapter for this NHI and check their
> +	 * status directly, but unfortunately USB4 seems to make it
> +	 * obnoxiously difficult to reliably make any correlation.
> +	 *
> +	 * So for now we'll have to bodge it... Hoping that the system
> +	 * is at least sane enough that an adapter is in the same PCI
> +	 * segment as its NHI, if we can find *something* on that segment
> +	 * which meets the requirements for Kernel DMA Protection, we'll
> +	 * take that to imply that firmware is aware and has (hopefully)
> +	 * done the right thing in general. We need to know that the PCI
> +	 * layer has seen the ExternalFacingPort property and propagated
> +	 * it to the "untrusted" flag that the IOMMU layer will then
> +	 * enforce, but also that the IOMMU driver itself can be trusted
> +	 * not to have been subverted by a pre-boot DMA attack.
> +	 */
> +	while (bus->parent)
> +		bus = bus->parent;
> +
> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
> +
> +	nhi->iommu_dma_protection = port_ok;
> +}
> +
>  static int nhi_init_msi(struct tb_nhi *nhi)
>  {
>  	struct pci_dev *pdev = nhi->pdev;
> @@ -1219,6 +1259,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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-18 22:29     ` Limonciello, Mario via iommu
  0 siblings, 0 replies; 24+ messages in thread
From: Limonciello, Mario via iommu @ 2022-03-18 22:29 UTC (permalink / raw)
  To: Robin Murphy, joro, baolu.lu, andreas.noever, michael.jamet,
	mika.westerberg, YehezkelShB
  Cc: iommu, linux-usb, linux-kernel, hch

[Public]

> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 

This approach looks generally good to me.  I do worry a little bit about older
systems that didn't set ExternalFacingPort in the FW but were previously setting
iommu_dma_protection, but I think that those could be treated on a quirk
basis to set PCI IDs for those root ports as external facing if/when they come
up.

I'll send up a follow up patch that adds the AMD ACPI table check.
If it looks good can roll it into your series for v3, or if this series goes
as is for v2 it can come on its own.

> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: Give up trying to look for specific devices, just look for evidence
>     that firmware cares at all.

I still do think you could know exactly which devices to use if you're in
SW CM mode, but I guess the consensus is to not bifurcate the way this
can be checked.

> 
>  drivers/thunderbolt/domain.c | 12 +++--------
>  drivers/thunderbolt/nhi.c    | 41
> ++++++++++++++++++++++++++++++++++++
>  include/linux/thunderbolt.h  |  2 ++
>  3 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
> index 7018d959f775..2889a214dadc 100644
> --- a/drivers/thunderbolt/domain.c
> +++ b/drivers/thunderbolt/domain.c
> @@ -7,9 +7,7 @@
>   */
> 
>  #include <linux/device.h>
> -#include <linux/dmar.h>
>  #include <linux/idr.h>
> -#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
> @@ -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 sysfs_emit(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..9e396e283792 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -14,6 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/pci.h>
>  #include <linux/interrupt.h>
> +#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/delay.h>
>  #include <linux/property.h>
> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>  		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>  }
> 
> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
> +{
> +	if (!pdev->untrusted ||
> +	    !dev_iommu_capable(&pdev->dev,
> IOMMU_CAP_PRE_BOOT_PROTECTION))
> +		return 0;
> +	*(bool *)data = true;
> +	return 1; /* Stop walking */
> +}
> +
> +static void nhi_check_iommu(struct tb_nhi *nhi)
> +{
> +	struct pci_bus *bus = nhi->pdev->bus;
> +	bool port_ok = false;
> +
> +	/*
> +	 * Ideally what we'd do here is grab every PCI device that
> +	 * represents a tunnelling adapter for this NHI and check their
> +	 * status directly, but unfortunately USB4 seems to make it
> +	 * obnoxiously difficult to reliably make any correlation.
> +	 *
> +	 * So for now we'll have to bodge it... Hoping that the system
> +	 * is at least sane enough that an adapter is in the same PCI
> +	 * segment as its NHI, if we can find *something* on that segment
> +	 * which meets the requirements for Kernel DMA Protection, we'll
> +	 * take that to imply that firmware is aware and has (hopefully)
> +	 * done the right thing in general. We need to know that the PCI
> +	 * layer has seen the ExternalFacingPort property and propagated
> +	 * it to the "untrusted" flag that the IOMMU layer will then
> +	 * enforce, but also that the IOMMU driver itself can be trusted
> +	 * not to have been subverted by a pre-boot DMA attack.
> +	 */
> +	while (bus->parent)
> +		bus = bus->parent;
> +
> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
> +
> +	nhi->iommu_dma_protection = port_ok;
> +}
> +
>  static int nhi_init_msi(struct tb_nhi *nhi)
>  {
>  	struct pci_dev *pdev = nhi->pdev;
> @@ -1219,6 +1259,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
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-18 22:29     ` Limonciello, Mario via iommu
@ 2022-03-21 10:58       ` mika.westerberg
  -1 siblings, 0 replies; 24+ messages in thread
From: mika.westerberg @ 2022-03-21 10:58 UTC (permalink / raw)
  To: Limonciello, Mario
  Cc: Robin Murphy, joro, baolu.lu, andreas.noever, michael.jamet,
	YehezkelShB, iommu, linux-usb, linux-kernel, hch

Hi Mario,

On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
> [Public]
> 
> > 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. While
> > that lets us assume kernel integrity, what matters for actual runtime
> > DMA protection is whether we trust individual devices, based on the
> > "external facing" property that we expect firmware to describe for
> > Thunderbolt ports.
> > 
> > It's proven challenging to determine the appropriate ports accurately
> > given the variety of possible topologies, so while still not getting a
> > perfect answer, by putting enough faith in firmware we can at least get
> > a good bit closer. If we can see that any device near a Thunderbolt NHI
> > has all the requisites for Kernel DMA Protection, chances are that it
> > *is* a relevant port, but moreover that implies that firmware is playing
> > the game overall, so we'll use that to assume that all Thunderbolt ports
> > should be correctly marked and thus will end up fully protected.
> > 
> 
> This approach looks generally good to me.  I do worry a little bit about older
> systems that didn't set ExternalFacingPort in the FW but were previously setting
> iommu_dma_protection, but I think that those could be treated on a quirk
> basis to set PCI IDs for those root ports as external facing if/when they come
> up.

There are no such systems out there AFAICT.

> I'll send up a follow up patch that adds the AMD ACPI table check.
> If it looks good can roll it into your series for v3, or if this series goes
> as is for v2 it can come on its own.
> 
> > CC: Mario Limonciello <mario.limonciello@amd.com>
> > Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> > ---
> > 
> > v2: Give up trying to look for specific devices, just look for evidence
> >     that firmware cares at all.
> 
> I still do think you could know exactly which devices to use if you're in
> SW CM mode, but I guess the consensus is to not bifurcate the way this
> can be checked.

Indeed.

The patch looks good to me now. I will give it a try on a couple of
systems later today or tomorrow and let you guys know how it went. I
don't expect any problems but let's see.

Thanks a lot Robin for working on this :)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-21 10:58       ` mika.westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: mika.westerberg @ 2022-03-21 10:58 UTC (permalink / raw)
  To: Limonciello, Mario
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	andreas.noever, Robin Murphy, hch

Hi Mario,

On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
> [Public]
> 
> > 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. While
> > that lets us assume kernel integrity, what matters for actual runtime
> > DMA protection is whether we trust individual devices, based on the
> > "external facing" property that we expect firmware to describe for
> > Thunderbolt ports.
> > 
> > It's proven challenging to determine the appropriate ports accurately
> > given the variety of possible topologies, so while still not getting a
> > perfect answer, by putting enough faith in firmware we can at least get
> > a good bit closer. If we can see that any device near a Thunderbolt NHI
> > has all the requisites for Kernel DMA Protection, chances are that it
> > *is* a relevant port, but moreover that implies that firmware is playing
> > the game overall, so we'll use that to assume that all Thunderbolt ports
> > should be correctly marked and thus will end up fully protected.
> > 
> 
> This approach looks generally good to me.  I do worry a little bit about older
> systems that didn't set ExternalFacingPort in the FW but were previously setting
> iommu_dma_protection, but I think that those could be treated on a quirk
> basis to set PCI IDs for those root ports as external facing if/when they come
> up.

There are no such systems out there AFAICT.

> I'll send up a follow up patch that adds the AMD ACPI table check.
> If it looks good can roll it into your series for v3, or if this series goes
> as is for v2 it can come on its own.
> 
> > CC: Mario Limonciello <mario.limonciello@amd.com>
> > Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> > ---
> > 
> > v2: Give up trying to look for specific devices, just look for evidence
> >     that firmware cares at all.
> 
> I still do think you could know exactly which devices to use if you're in
> SW CM mode, but I guess the consensus is to not bifurcate the way this
> can be checked.

Indeed.

The patch looks good to me now. I will give it a try on a couple of
systems later today or tomorrow and let you guys know how it went. I
don't expect any problems but let's see.

Thanks a lot Robin for working on this :)
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-21 10:58       ` mika.westerberg
@ 2022-03-21 11:11         ` Robin Murphy
  -1 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-21 11:11 UTC (permalink / raw)
  To: mika.westerberg, Limonciello, Mario
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, YehezkelShB,
	iommu, linux-usb, linux-kernel, hch

On 2022-03-21 10:58, mika.westerberg@linux.intel.com wrote:
> Hi Mario,
> 
> On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
>> [Public]
>>
>>> 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. While
>>> that lets us assume kernel integrity, what matters for actual runtime
>>> DMA protection is whether we trust individual devices, based on the
>>> "external facing" property that we expect firmware to describe for
>>> Thunderbolt ports.
>>>
>>> It's proven challenging to determine the appropriate ports accurately
>>> given the variety of possible topologies, so while still not getting a
>>> perfect answer, by putting enough faith in firmware we can at least get
>>> a good bit closer. If we can see that any device near a Thunderbolt NHI
>>> has all the requisites for Kernel DMA Protection, chances are that it
>>> *is* a relevant port, but moreover that implies that firmware is playing
>>> the game overall, so we'll use that to assume that all Thunderbolt ports
>>> should be correctly marked and thus will end up fully protected.
>>>
>>
>> This approach looks generally good to me.  I do worry a little bit about older
>> systems that didn't set ExternalFacingPort in the FW but were previously setting
>> iommu_dma_protection, but I think that those could be treated on a quirk
>> basis to set PCI IDs for those root ports as external facing if/when they come
>> up.
> 
> There are no such systems out there AFAICT.

And even if there are, as above they've never actually been fully 
protected and still won't be, so it's arguably a good thing for them to 
stop thinking so.

>> I'll send up a follow up patch that adds the AMD ACPI table check.
>> If it looks good can roll it into your series for v3, or if this series goes
>> as is for v2 it can come on its own.
>>
>>> CC: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>>> ---
>>>
>>> v2: Give up trying to look for specific devices, just look for evidence
>>>      that firmware cares at all.
>>
>> I still do think you could know exactly which devices to use if you're in
>> SW CM mode, but I guess the consensus is to not bifurcate the way this
>> can be checked.
> 
> Indeed.
> 
> The patch looks good to me now. I will give it a try on a couple of
> systems later today or tomorrow and let you guys know how it went. I
> don't expect any problems but let's see.
> 
> Thanks a lot Robin for working on this :)

Heh, let's just hope the other half-dozen or so subsystems I need to 
touch for this IOMMU cleanup aren't all quite as involved as this turned 
out to be :)

Cheers,
Robin.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-21 11:11         ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-21 11:11 UTC (permalink / raw)
  To: mika.westerberg, Limonciello, Mario
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	andreas.noever, hch

On 2022-03-21 10:58, mika.westerberg@linux.intel.com wrote:
> Hi Mario,
> 
> On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
>> [Public]
>>
>>> 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. While
>>> that lets us assume kernel integrity, what matters for actual runtime
>>> DMA protection is whether we trust individual devices, based on the
>>> "external facing" property that we expect firmware to describe for
>>> Thunderbolt ports.
>>>
>>> It's proven challenging to determine the appropriate ports accurately
>>> given the variety of possible topologies, so while still not getting a
>>> perfect answer, by putting enough faith in firmware we can at least get
>>> a good bit closer. If we can see that any device near a Thunderbolt NHI
>>> has all the requisites for Kernel DMA Protection, chances are that it
>>> *is* a relevant port, but moreover that implies that firmware is playing
>>> the game overall, so we'll use that to assume that all Thunderbolt ports
>>> should be correctly marked and thus will end up fully protected.
>>>
>>
>> This approach looks generally good to me.  I do worry a little bit about older
>> systems that didn't set ExternalFacingPort in the FW but were previously setting
>> iommu_dma_protection, but I think that those could be treated on a quirk
>> basis to set PCI IDs for those root ports as external facing if/when they come
>> up.
> 
> There are no such systems out there AFAICT.

And even if there are, as above they've never actually been fully 
protected and still won't be, so it's arguably a good thing for them to 
stop thinking so.

>> I'll send up a follow up patch that adds the AMD ACPI table check.
>> If it looks good can roll it into your series for v3, or if this series goes
>> as is for v2 it can come on its own.
>>
>>> CC: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>>> ---
>>>
>>> v2: Give up trying to look for specific devices, just look for evidence
>>>      that firmware cares at all.
>>
>> I still do think you could know exactly which devices to use if you're in
>> SW CM mode, but I guess the consensus is to not bifurcate the way this
>> can be checked.
> 
> Indeed.
> 
> The patch looks good to me now. I will give it a try on a couple of
> systems later today or tomorrow and let you guys know how it went. I
> don't expect any problems but let's see.
> 
> Thanks a lot Robin for working on this :)

Heh, let's just hope the other half-dozen or so subsystems I need to 
touch for this IOMMU cleanup aren't all quite as involved as this turned 
out to be :)

Cheers,
Robin.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-21 11:11         ` Robin Murphy
@ 2022-03-21 13:21           ` Limonciello, Mario via iommu
  -1 siblings, 0 replies; 24+ messages in thread
From: Limonciello, Mario @ 2022-03-21 13:21 UTC (permalink / raw)
  To: Robin Murphy, mika.westerberg
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, YehezkelShB,
	iommu, linux-usb, linux-kernel, hch

[Public]



> -----Original Message-----
> From: Robin Murphy <robin.murphy@arm.com>
> Sent: Monday, March 21, 2022 06:12
> To: mika.westerberg@linux.intel.com; Limonciello, Mario
> <Mario.Limonciello@amd.com>
> Cc: joro@8bytes.org; baolu.lu@linux.intel.com; andreas.noever@gmail.com;
> michael.jamet@intel.com; YehezkelShB@gmail.com; iommu@lists.linux-
> foundation.org; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org;
> hch@lst.de
> Subject: Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection
> more accurate
> 
> On 2022-03-21 10:58, mika.westerberg@linux.intel.com wrote:
> > Hi Mario,
> >
> > On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
> >> [Public]
> >>
> >>> 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. While
> >>> that lets us assume kernel integrity, what matters for actual runtime
> >>> DMA protection is whether we trust individual devices, based on the
> >>> "external facing" property that we expect firmware to describe for
> >>> Thunderbolt ports.
> >>>
> >>> It's proven challenging to determine the appropriate ports accurately
> >>> given the variety of possible topologies, so while still not getting a
> >>> perfect answer, by putting enough faith in firmware we can at least get
> >>> a good bit closer. If we can see that any device near a Thunderbolt NHI
> >>> has all the requisites for Kernel DMA Protection, chances are that it
> >>> *is* a relevant port, but moreover that implies that firmware is playing
> >>> the game overall, so we'll use that to assume that all Thunderbolt ports
> >>> should be correctly marked and thus will end up fully protected.
> >>>
> >>
> >> This approach looks generally good to me.  I do worry a little bit about
> older
> >> systems that didn't set ExternalFacingPort in the FW but were previously
> setting
> >> iommu_dma_protection, but I think that those could be treated on a
> quirk
> >> basis to set PCI IDs for those root ports as external facing if/when they
> come
> >> up.
> >
> > There are no such systems out there AFAICT.
> 
> And even if there are, as above they've never actually been fully
> protected and still won't be, so it's arguably a good thing for them to
> stop thinking so.

I was meaning that if this situation comes up that we could tag the PCI IDs for
those root ports as ExternalFacing in drivers/pci/quirks.c so that the protection
"is" enacted for them even if it was missing from the firmware.

> 
> >> I'll send up a follow up patch that adds the AMD ACPI table check.
> >> If it looks good can roll it into your series for v3, or if this series goes
> >> as is for v2 it can come on its own.
> >>
> >>> CC: Mario Limonciello <mario.limonciello@amd.com>
> >>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> >>> ---
> >>>
> >>> v2: Give up trying to look for specific devices, just look for evidence
> >>>      that firmware cares at all.
> >>
> >> I still do think you could know exactly which devices to use if you're in
> >> SW CM mode, but I guess the consensus is to not bifurcate the way this
> >> can be checked.
> >
> > Indeed.
> >
> > The patch looks good to me now. I will give it a try on a couple of
> > systems later today or tomorrow and let you guys know how it went. I
> > don't expect any problems but let's see.
> >
> > Thanks a lot Robin for working on this :)
> 
> Heh, let's just hope the other half-dozen or so subsystems I need to
> touch for this IOMMU cleanup aren't all quite as involved as this turned
> out to be :)

Thanks a lot for this effort!

> 
> Cheers,
> Robin.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-21 13:21           ` Limonciello, Mario via iommu
  0 siblings, 0 replies; 24+ messages in thread
From: Limonciello, Mario via iommu @ 2022-03-21 13:21 UTC (permalink / raw)
  To: Robin Murphy, mika.westerberg
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	andreas.noever, hch

[Public]



> -----Original Message-----
> From: Robin Murphy <robin.murphy@arm.com>
> Sent: Monday, March 21, 2022 06:12
> To: mika.westerberg@linux.intel.com; Limonciello, Mario
> <Mario.Limonciello@amd.com>
> Cc: joro@8bytes.org; baolu.lu@linux.intel.com; andreas.noever@gmail.com;
> michael.jamet@intel.com; YehezkelShB@gmail.com; iommu@lists.linux-
> foundation.org; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org;
> hch@lst.de
> Subject: Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection
> more accurate
> 
> On 2022-03-21 10:58, mika.westerberg@linux.intel.com wrote:
> > Hi Mario,
> >
> > On Fri, Mar 18, 2022 at 10:29:59PM +0000, Limonciello, Mario wrote:
> >> [Public]
> >>
> >>> 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. While
> >>> that lets us assume kernel integrity, what matters for actual runtime
> >>> DMA protection is whether we trust individual devices, based on the
> >>> "external facing" property that we expect firmware to describe for
> >>> Thunderbolt ports.
> >>>
> >>> It's proven challenging to determine the appropriate ports accurately
> >>> given the variety of possible topologies, so while still not getting a
> >>> perfect answer, by putting enough faith in firmware we can at least get
> >>> a good bit closer. If we can see that any device near a Thunderbolt NHI
> >>> has all the requisites for Kernel DMA Protection, chances are that it
> >>> *is* a relevant port, but moreover that implies that firmware is playing
> >>> the game overall, so we'll use that to assume that all Thunderbolt ports
> >>> should be correctly marked and thus will end up fully protected.
> >>>
> >>
> >> This approach looks generally good to me.  I do worry a little bit about
> older
> >> systems that didn't set ExternalFacingPort in the FW but were previously
> setting
> >> iommu_dma_protection, but I think that those could be treated on a
> quirk
> >> basis to set PCI IDs for those root ports as external facing if/when they
> come
> >> up.
> >
> > There are no such systems out there AFAICT.
> 
> And even if there are, as above they've never actually been fully
> protected and still won't be, so it's arguably a good thing for them to
> stop thinking so.

I was meaning that if this situation comes up that we could tag the PCI IDs for
those root ports as ExternalFacing in drivers/pci/quirks.c so that the protection
"is" enacted for them even if it was missing from the firmware.

> 
> >> I'll send up a follow up patch that adds the AMD ACPI table check.
> >> If it looks good can roll it into your series for v3, or if this series goes
> >> as is for v2 it can come on its own.
> >>
> >>> CC: Mario Limonciello <mario.limonciello@amd.com>
> >>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> >>> ---
> >>>
> >>> v2: Give up trying to look for specific devices, just look for evidence
> >>>      that firmware cares at all.
> >>
> >> I still do think you could know exactly which devices to use if you're in
> >> SW CM mode, but I guess the consensus is to not bifurcate the way this
> >> can be checked.
> >
> > Indeed.
> >
> > The patch looks good to me now. I will give it a try on a couple of
> > systems later today or tomorrow and let you guys know how it went. I
> > don't expect any problems but let's see.
> >
> > Thanks a lot Robin for working on this :)
> 
> Heh, let's just hope the other half-dozen or so subsystems I need to
> touch for this IOMMU cleanup aren't all quite as involved as this turned
> out to be :)

Thanks a lot for this effort!

> 
> Cheers,
> Robin.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
  2022-03-18 17:42   ` Robin Murphy
@ 2022-03-22  9:14     ` Christoph Hellwig
  -1 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2022-03-22  9:14 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB, iommu, linux-usb, linux-kernel, mario.limonciello,
	hch

On Fri, Mar 18, 2022 at 05:42:57PM +0000, Robin Murphy wrote:
> VT-d's dmar_platform_optin() actually represents a combination of
> properties fairly well standardised by Microsoft as "Pre-boot DMA
> Protection" and "Kernel DMA Protection"[1]. As such, we can provide
> interested consumers with an abstracted capability rather than
> driver-specific interfaces that won't scale. We name it for the former
> aspect since that's what external callers are most likely to be
> interested in; the latter is for the IOMMU layer to handle itself.
> 
> Also use this as an opportunity to draw a line in the sand and add a
> new interface so as not to introduce any more callers of iommu_capable()
> which I also want to get rid of. For now it's a quick'n'dirty wrapper
> function, but will evolve to subsume the internal interface in future.
> 
> [1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection
> 
> Suggested-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

I can't really think of a way in which I suggested this, but it does
looks like a good interface:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
@ 2022-03-22  9:14     ` Christoph Hellwig
  0 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2022-03-22  9:14 UTC (permalink / raw)
  To: Robin Murphy
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	mario.limonciello, andreas.noever, mika.westerberg, hch

On Fri, Mar 18, 2022 at 05:42:57PM +0000, Robin Murphy wrote:
> VT-d's dmar_platform_optin() actually represents a combination of
> properties fairly well standardised by Microsoft as "Pre-boot DMA
> Protection" and "Kernel DMA Protection"[1]. As such, we can provide
> interested consumers with an abstracted capability rather than
> driver-specific interfaces that won't scale. We name it for the former
> aspect since that's what external callers are most likely to be
> interested in; the latter is for the IOMMU layer to handle itself.
> 
> Also use this as an opportunity to draw a line in the sand and add a
> new interface so as not to introduce any more callers of iommu_capable()
> which I also want to get rid of. For now it's a quick'n'dirty wrapper
> function, but will evolve to subsume the internal interface in future.
> 
> [1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection
> 
> Suggested-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

I can't really think of a way in which I suggested this, but it does
looks like a good interface:

Reviewed-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-18 17:42   ` Robin Murphy
@ 2022-03-22  9:16     ` Christoph Hellwig
  -1 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2022-03-22  9:16 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, mika.westerberg,
	YehezkelShB, iommu, linux-usb, linux-kernel, mario.limonciello,
	hch

On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 
> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Looks sensible to me:

Acked-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-22  9:16     ` Christoph Hellwig
  0 siblings, 0 replies; 24+ messages in thread
From: Christoph Hellwig @ 2022-03-22  9:16 UTC (permalink / raw)
  To: Robin Murphy
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	mario.limonciello, andreas.noever, mika.westerberg, hch

On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 
> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Looks sensible to me:

Acked-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
  2022-03-22  9:14     ` Christoph Hellwig
@ 2022-03-22  9:53       ` Robin Murphy
  -1 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-22  9:53 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	mario.limonciello, andreas.noever, mika.westerberg

On 2022-03-22 09:14, Christoph Hellwig wrote:
> On Fri, Mar 18, 2022 at 05:42:57PM +0000, Robin Murphy wrote:
>> VT-d's dmar_platform_optin() actually represents a combination of
>> properties fairly well standardised by Microsoft as "Pre-boot DMA
>> Protection" and "Kernel DMA Protection"[1]. As such, we can provide
>> interested consumers with an abstracted capability rather than
>> driver-specific interfaces that won't scale. We name it for the former
>> aspect since that's what external callers are most likely to be
>> interested in; the latter is for the IOMMU layer to handle itself.
>>
>> Also use this as an opportunity to draw a line in the sand and add a
>> new interface so as not to introduce any more callers of iommu_capable()
>> which I also want to get rid of. For now it's a quick'n'dirty wrapper
>> function, but will evolve to subsume the internal interface in future.
>>
>> [1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection
>>
>> Suggested-by: Christoph Hellwig <hch@lst.de>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> 
> I can't really think of a way in which I suggested this, but it does
> looks like a good interface:

Well, you were the first to say it should be abstracted[1], and since my 
initial thought that it could be hidden completely didn't pan out, I 
felt I should give you credit for being right all along :)

> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thanks!

Robin.

[1] https://lore.kernel.org/linux-iommu/YjDDUUeZ%2FdvUZoDN@infradead.org/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection
@ 2022-03-22  9:53       ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-22  9:53 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: michael.jamet, linux-usb, linux-kernel, andreas.noever, iommu,
	mario.limonciello, YehezkelShB, mika.westerberg

On 2022-03-22 09:14, Christoph Hellwig wrote:
> On Fri, Mar 18, 2022 at 05:42:57PM +0000, Robin Murphy wrote:
>> VT-d's dmar_platform_optin() actually represents a combination of
>> properties fairly well standardised by Microsoft as "Pre-boot DMA
>> Protection" and "Kernel DMA Protection"[1]. As such, we can provide
>> interested consumers with an abstracted capability rather than
>> driver-specific interfaces that won't scale. We name it for the former
>> aspect since that's what external callers are most likely to be
>> interested in; the latter is for the IOMMU layer to handle itself.
>>
>> Also use this as an opportunity to draw a line in the sand and add a
>> new interface so as not to introduce any more callers of iommu_capable()
>> which I also want to get rid of. For now it's a quick'n'dirty wrapper
>> function, but will evolve to subsume the internal interface in future.
>>
>> [1] https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-kernel-dma-protection
>>
>> Suggested-by: Christoph Hellwig <hch@lst.de>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> 
> I can't really think of a way in which I suggested this, but it does
> looks like a good interface:

Well, you were the first to say it should be abstracted[1], and since my 
initial thought that it could be hidden completely didn't pan out, I 
felt I should give you credit for being right all along :)

> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thanks!

Robin.

[1] https://lore.kernel.org/linux-iommu/YjDDUUeZ%2FdvUZoDN@infradead.org/
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-18 17:42   ` Robin Murphy
@ 2022-03-22 11:41     ` Mika Westerberg
  -1 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2022-03-22 11:41 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, YehezkelShB,
	iommu, linux-usb, linux-kernel, mario.limonciello, hch

Hi Robin,

I tried this now on two Intel systems. One with integrated Thunderbolt
and one with discrete. There was a small issue, see below but once fixed
it worked as expected :)

On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 
> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: Give up trying to look for specific devices, just look for evidence
>     that firmware cares at all.
> 
>  drivers/thunderbolt/domain.c | 12 +++--------
>  drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
>  include/linux/thunderbolt.h  |  2 ++
>  3 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
> index 7018d959f775..2889a214dadc 100644
> --- a/drivers/thunderbolt/domain.c
> +++ b/drivers/thunderbolt/domain.c
> @@ -7,9 +7,7 @@
>   */
>  
>  #include <linux/device.h>
> -#include <linux/dmar.h>
>  #include <linux/idr.h>
> -#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
> @@ -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 sysfs_emit(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..9e396e283792 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -14,6 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/pci.h>
>  #include <linux/interrupt.h>
> +#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/delay.h>
>  #include <linux/property.h>
> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>  		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>  }
>  
> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
> +{
> +	if (!pdev->untrusted ||
> +	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

This one needs to take the pdev->external_facing into account too
because most of the time there are no existing tunnels when the driver
is loaded so we only see the PCIe root/downstream port. I think this is
enough actually:

	if (!pdev->external_facing ||
	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

> +		return 0;
> +	*(bool *)data = true;
> +	return 1; /* Stop walking */
> +}
> +
> +static void nhi_check_iommu(struct tb_nhi *nhi)
> +{
> +	struct pci_bus *bus = nhi->pdev->bus;
> +	bool port_ok = false;
> +
> +	/*
> +	 * Ideally what we'd do here is grab every PCI device that
> +	 * represents a tunnelling adapter for this NHI and check their
> +	 * status directly, but unfortunately USB4 seems to make it
> +	 * obnoxiously difficult to reliably make any correlation.
> +	 *
> +	 * So for now we'll have to bodge it... Hoping that the system
> +	 * is at least sane enough that an adapter is in the same PCI
> +	 * segment as its NHI, if we can find *something* on that segment
> +	 * which meets the requirements for Kernel DMA Protection, we'll
> +	 * take that to imply that firmware is aware and has (hopefully)
> +	 * done the right thing in general. We need to know that the PCI
> +	 * layer has seen the ExternalFacingPort property and propagated
> +	 * it to the "untrusted" flag that the IOMMU layer will then
> +	 * enforce, but also that the IOMMU driver itself can be trusted
> +	 * not to have been subverted by a pre-boot DMA attack.
> +	 */
> +	while (bus->parent)
> +		bus = bus->parent;
> +
> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
> +
> +	nhi->iommu_dma_protection = port_ok;

I would put here a log debug, something like this:

dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %sabled\n",
	port_ok ? "en" : "dis");

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-22 11:41     ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2022-03-22 11:41 UTC (permalink / raw)
  To: Robin Murphy
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	mario.limonciello, andreas.noever, hch

Hi Robin,

I tried this now on two Intel systems. One with integrated Thunderbolt
and one with discrete. There was a small issue, see below but once fixed
it worked as expected :)

On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
> 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. While
> that lets us assume kernel integrity, what matters for actual runtime
> DMA protection is whether we trust individual devices, based on the
> "external facing" property that we expect firmware to describe for
> Thunderbolt ports.
> 
> It's proven challenging to determine the appropriate ports accurately
> given the variety of possible topologies, so while still not getting a
> perfect answer, by putting enough faith in firmware we can at least get
> a good bit closer. If we can see that any device near a Thunderbolt NHI
> has all the requisites for Kernel DMA Protection, chances are that it
> *is* a relevant port, but moreover that implies that firmware is playing
> the game overall, so we'll use that to assume that all Thunderbolt ports
> should be correctly marked and thus will end up fully protected.
> 
> CC: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: Give up trying to look for specific devices, just look for evidence
>     that firmware cares at all.
> 
>  drivers/thunderbolt/domain.c | 12 +++--------
>  drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
>  include/linux/thunderbolt.h  |  2 ++
>  3 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
> index 7018d959f775..2889a214dadc 100644
> --- a/drivers/thunderbolt/domain.c
> +++ b/drivers/thunderbolt/domain.c
> @@ -7,9 +7,7 @@
>   */
>  
>  #include <linux/device.h>
> -#include <linux/dmar.h>
>  #include <linux/idr.h>
> -#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
> @@ -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 sysfs_emit(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..9e396e283792 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -14,6 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/pci.h>
>  #include <linux/interrupt.h>
> +#include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/delay.h>
>  #include <linux/property.h>
> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>  		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>  }
>  
> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
> +{
> +	if (!pdev->untrusted ||
> +	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

This one needs to take the pdev->external_facing into account too
because most of the time there are no existing tunnels when the driver
is loaded so we only see the PCIe root/downstream port. I think this is
enough actually:

	if (!pdev->external_facing ||
	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

> +		return 0;
> +	*(bool *)data = true;
> +	return 1; /* Stop walking */
> +}
> +
> +static void nhi_check_iommu(struct tb_nhi *nhi)
> +{
> +	struct pci_bus *bus = nhi->pdev->bus;
> +	bool port_ok = false;
> +
> +	/*
> +	 * Ideally what we'd do here is grab every PCI device that
> +	 * represents a tunnelling adapter for this NHI and check their
> +	 * status directly, but unfortunately USB4 seems to make it
> +	 * obnoxiously difficult to reliably make any correlation.
> +	 *
> +	 * So for now we'll have to bodge it... Hoping that the system
> +	 * is at least sane enough that an adapter is in the same PCI
> +	 * segment as its NHI, if we can find *something* on that segment
> +	 * which meets the requirements for Kernel DMA Protection, we'll
> +	 * take that to imply that firmware is aware and has (hopefully)
> +	 * done the right thing in general. We need to know that the PCI
> +	 * layer has seen the ExternalFacingPort property and propagated
> +	 * it to the "untrusted" flag that the IOMMU layer will then
> +	 * enforce, but also that the IOMMU driver itself can be trusted
> +	 * not to have been subverted by a pre-boot DMA attack.
> +	 */
> +	while (bus->parent)
> +		bus = bus->parent;
> +
> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
> +
> +	nhi->iommu_dma_protection = port_ok;

I would put here a log debug, something like this:

dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %sabled\n",
	port_ok ? "en" : "dis");
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
  2022-03-22 11:41     ` Mika Westerberg
@ 2022-03-22 14:40       ` Robin Murphy
  -1 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-22 14:40 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: joro, baolu.lu, andreas.noever, michael.jamet, YehezkelShB,
	iommu, linux-usb, linux-kernel, mario.limonciello, hch

On 2022-03-22 11:41, Mika Westerberg wrote:
> Hi Robin,
> 
> I tried this now on two Intel systems. One with integrated Thunderbolt
> and one with discrete. There was a small issue, see below but once fixed
> it worked as expected :)
> 
> On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
>> 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. While
>> that lets us assume kernel integrity, what matters for actual runtime
>> DMA protection is whether we trust individual devices, based on the
>> "external facing" property that we expect firmware to describe for
>> Thunderbolt ports.
>>
>> It's proven challenging to determine the appropriate ports accurately
>> given the variety of possible topologies, so while still not getting a
>> perfect answer, by putting enough faith in firmware we can at least get
>> a good bit closer. If we can see that any device near a Thunderbolt NHI
>> has all the requisites for Kernel DMA Protection, chances are that it
>> *is* a relevant port, but moreover that implies that firmware is playing
>> the game overall, so we'll use that to assume that all Thunderbolt ports
>> should be correctly marked and thus will end up fully protected.
>>
>> CC: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>> ---
>>
>> v2: Give up trying to look for specific devices, just look for evidence
>>      that firmware cares at all.
>>
>>   drivers/thunderbolt/domain.c | 12 +++--------
>>   drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
>>   include/linux/thunderbolt.h  |  2 ++
>>   3 files changed, 46 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
>> index 7018d959f775..2889a214dadc 100644
>> --- a/drivers/thunderbolt/domain.c
>> +++ b/drivers/thunderbolt/domain.c
>> @@ -7,9 +7,7 @@
>>    */
>>   
>>   #include <linux/device.h>
>> -#include <linux/dmar.h>
>>   #include <linux/idr.h>
>> -#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/pm_runtime.h>
>>   #include <linux/slab.h>
>> @@ -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 sysfs_emit(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..9e396e283792 100644
>> --- a/drivers/thunderbolt/nhi.c
>> +++ b/drivers/thunderbolt/nhi.c
>> @@ -14,6 +14,7 @@
>>   #include <linux/errno.h>
>>   #include <linux/pci.h>
>>   #include <linux/interrupt.h>
>> +#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/delay.h>
>>   #include <linux/property.h>
>> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>>   		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>>   }
>>   
>> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
>> +{
>> +	if (!pdev->untrusted ||
>> +	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))
> 
> This one needs to take the pdev->external_facing into account too
> because most of the time there are no existing tunnels when the driver
> is loaded so we only see the PCIe root/downstream port. I think this is
> enough actually:
> 
> 	if (!pdev->external_facing ||
> 	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

Ah yes, my bad, for some reason I got the misapprehension into my head 
that untrusted was propagated to the port as well, not just the devices 
behind it. I'll fix this and tweak the comment below to match.

>> +		return 0;
>> +	*(bool *)data = true;
>> +	return 1; /* Stop walking */
>> +}
>> +
>> +static void nhi_check_iommu(struct tb_nhi *nhi)
>> +{
>> +	struct pci_bus *bus = nhi->pdev->bus;
>> +	bool port_ok = false;
>> +
>> +	/*
>> +	 * Ideally what we'd do here is grab every PCI device that
>> +	 * represents a tunnelling adapter for this NHI and check their
>> +	 * status directly, but unfortunately USB4 seems to make it
>> +	 * obnoxiously difficult to reliably make any correlation.
>> +	 *
>> +	 * So for now we'll have to bodge it... Hoping that the system
>> +	 * is at least sane enough that an adapter is in the same PCI
>> +	 * segment as its NHI, if we can find *something* on that segment
>> +	 * which meets the requirements for Kernel DMA Protection, we'll
>> +	 * take that to imply that firmware is aware and has (hopefully)
>> +	 * done the right thing in general. We need to know that the PCI
>> +	 * layer has seen the ExternalFacingPort property and propagated
>> +	 * it to the "untrusted" flag that the IOMMU layer will then
>> +	 * enforce, but also that the IOMMU driver itself can be trusted
>> +	 * not to have been subverted by a pre-boot DMA attack.
>> +	 */
>> +	while (bus->parent)
>> +		bus = bus->parent;
>> +
>> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
>> +
>> +	nhi->iommu_dma_protection = port_ok;
> 
> I would put here a log debug, something like this:
> 
> dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %sabled\n",
> 	port_ok ? "en" : "dis");

Ack. I'll wait and send a v3 once the merge window's over, and can roll 
Mario's AMD IOMMU patch into that too.

Thanks,
Robin.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate
@ 2022-03-22 14:40       ` Robin Murphy
  0 siblings, 0 replies; 24+ messages in thread
From: Robin Murphy @ 2022-03-22 14:40 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: michael.jamet, linux-usb, linux-kernel, YehezkelShB, iommu,
	mario.limonciello, andreas.noever, hch

On 2022-03-22 11:41, Mika Westerberg wrote:
> Hi Robin,
> 
> I tried this now on two Intel systems. One with integrated Thunderbolt
> and one with discrete. There was a small issue, see below but once fixed
> it worked as expected :)
> 
> On Fri, Mar 18, 2022 at 05:42:58PM +0000, Robin Murphy wrote:
>> 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. While
>> that lets us assume kernel integrity, what matters for actual runtime
>> DMA protection is whether we trust individual devices, based on the
>> "external facing" property that we expect firmware to describe for
>> Thunderbolt ports.
>>
>> It's proven challenging to determine the appropriate ports accurately
>> given the variety of possible topologies, so while still not getting a
>> perfect answer, by putting enough faith in firmware we can at least get
>> a good bit closer. If we can see that any device near a Thunderbolt NHI
>> has all the requisites for Kernel DMA Protection, chances are that it
>> *is* a relevant port, but moreover that implies that firmware is playing
>> the game overall, so we'll use that to assume that all Thunderbolt ports
>> should be correctly marked and thus will end up fully protected.
>>
>> CC: Mario Limonciello <mario.limonciello@amd.com>
>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>> ---
>>
>> v2: Give up trying to look for specific devices, just look for evidence
>>      that firmware cares at all.
>>
>>   drivers/thunderbolt/domain.c | 12 +++--------
>>   drivers/thunderbolt/nhi.c    | 41 ++++++++++++++++++++++++++++++++++++
>>   include/linux/thunderbolt.h  |  2 ++
>>   3 files changed, 46 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
>> index 7018d959f775..2889a214dadc 100644
>> --- a/drivers/thunderbolt/domain.c
>> +++ b/drivers/thunderbolt/domain.c
>> @@ -7,9 +7,7 @@
>>    */
>>   
>>   #include <linux/device.h>
>> -#include <linux/dmar.h>
>>   #include <linux/idr.h>
>> -#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/pm_runtime.h>
>>   #include <linux/slab.h>
>> @@ -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 sysfs_emit(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..9e396e283792 100644
>> --- a/drivers/thunderbolt/nhi.c
>> +++ b/drivers/thunderbolt/nhi.c
>> @@ -14,6 +14,7 @@
>>   #include <linux/errno.h>
>>   #include <linux/pci.h>
>>   #include <linux/interrupt.h>
>> +#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/delay.h>
>>   #include <linux/property.h>
>> @@ -1102,6 +1103,45 @@ static void nhi_check_quirks(struct tb_nhi *nhi)
>>   		nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
>>   }
>>   
>> +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
>> +{
>> +	if (!pdev->untrusted ||
>> +	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))
> 
> This one needs to take the pdev->external_facing into account too
> because most of the time there are no existing tunnels when the driver
> is loaded so we only see the PCIe root/downstream port. I think this is
> enough actually:
> 
> 	if (!pdev->external_facing ||
> 	    !dev_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION))

Ah yes, my bad, for some reason I got the misapprehension into my head 
that untrusted was propagated to the port as well, not just the devices 
behind it. I'll fix this and tweak the comment below to match.

>> +		return 0;
>> +	*(bool *)data = true;
>> +	return 1; /* Stop walking */
>> +}
>> +
>> +static void nhi_check_iommu(struct tb_nhi *nhi)
>> +{
>> +	struct pci_bus *bus = nhi->pdev->bus;
>> +	bool port_ok = false;
>> +
>> +	/*
>> +	 * Ideally what we'd do here is grab every PCI device that
>> +	 * represents a tunnelling adapter for this NHI and check their
>> +	 * status directly, but unfortunately USB4 seems to make it
>> +	 * obnoxiously difficult to reliably make any correlation.
>> +	 *
>> +	 * So for now we'll have to bodge it... Hoping that the system
>> +	 * is at least sane enough that an adapter is in the same PCI
>> +	 * segment as its NHI, if we can find *something* on that segment
>> +	 * which meets the requirements for Kernel DMA Protection, we'll
>> +	 * take that to imply that firmware is aware and has (hopefully)
>> +	 * done the right thing in general. We need to know that the PCI
>> +	 * layer has seen the ExternalFacingPort property and propagated
>> +	 * it to the "untrusted" flag that the IOMMU layer will then
>> +	 * enforce, but also that the IOMMU driver itself can be trusted
>> +	 * not to have been subverted by a pre-boot DMA attack.
>> +	 */
>> +	while (bus->parent)
>> +		bus = bus->parent;
>> +
>> +	pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok);
>> +
>> +	nhi->iommu_dma_protection = port_ok;
> 
> I would put here a log debug, something like this:
> 
> dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %sabled\n",
> 	port_ok ? "en" : "dis");

Ack. I'll wait and send a v3 once the merge window's over, and can roll 
Mario's AMD IOMMU patch into that too.

Thanks,
Robin.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2022-03-22 14:40 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-18 17:42 [PATCH v2 0/2] thunderbolt: Make iommu_dma_protection more accurate Robin Murphy
2022-03-18 17:42 ` Robin Murphy
2022-03-18 17:42 ` [PATCH v2 1/2] iommu: Add capability for pre-boot DMA protection Robin Murphy
2022-03-18 17:42   ` Robin Murphy
2022-03-22  9:14   ` Christoph Hellwig
2022-03-22  9:14     ` Christoph Hellwig
2022-03-22  9:53     ` Robin Murphy
2022-03-22  9:53       ` Robin Murphy
2022-03-18 17:42 ` [PATCH v2 2/2] thunderbolt: Make iommu_dma_protection more accurate Robin Murphy
2022-03-18 17:42   ` Robin Murphy
2022-03-18 22:29   ` Limonciello, Mario
2022-03-18 22:29     ` Limonciello, Mario via iommu
2022-03-21 10:58     ` mika.westerberg
2022-03-21 10:58       ` mika.westerberg
2022-03-21 11:11       ` Robin Murphy
2022-03-21 11:11         ` Robin Murphy
2022-03-21 13:21         ` Limonciello, Mario
2022-03-21 13:21           ` Limonciello, Mario via iommu
2022-03-22  9:16   ` Christoph Hellwig
2022-03-22  9:16     ` Christoph Hellwig
2022-03-22 11:41   ` Mika Westerberg
2022-03-22 11:41     ` Mika Westerberg
2022-03-22 14:40     ` Robin Murphy
2022-03-22 14:40       ` Robin Murphy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.