All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iommu/vt-d: Fix scatterlist offset handling
@ 2017-09-28 14:14 Robin Murphy
  2017-09-28 16:17 ` Casey Leedom
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Robin Murphy @ 2017-09-28 14:14 UTC (permalink / raw)
  To: joro
  Cc: dwmw2, ashok.raj, leedom, Harsh, herbert, iommu, linux-crypto,
	linux-kernel

The intel-iommu DMA ops fail to correctly handle scatterlists where
sg->offset is greater than PAGE_SIZE - the IOVA allocation is computed
appropriately based on the page-aligned portion of the offset, but the
mapping is set up relative to sg->page, which means it fails to actually
cover the whole buffer (and in the worst case doesn't cover it at all):

    (sg->dma_address + sg->dma_len) ----+
    sg->dma_address ---------+          |
    iov_pfn------+           |          |
                 |           |          |
                 v           v          v
iova:   a        b        c        d        e        f
        |--------|--------|--------|--------|--------|
                          <...calculated....>
                 [_____mapped______]
pfn:    0        1        2        3        4        5
        |--------|--------|--------|--------|--------|
                 ^           ^          ^
                 |           |          |
    sg->page ----+           |          |
    sg->offset --------------+          |
    (sg->offset + sg->length) ----------+

As a result, the caller ends up overrunning the mapping into whatever
lies beyond, which usually goes badly:

[  429.645492] DMAR: DRHD: handling fault status reg 2
[  429.650847] DMAR: [DMA Write] Request device [02:00.4] fault addr f2682000 ...

Whilst this is a fairly rare occurrence, it can happen from the result
of intermediate scatterlist processing such as scatterwalk_ffwd() in the
crypto layer. Whilst that particular site could be fixed up, it still
seems worthwhile to bring intel-iommu in line with other DMA API
implementations in handling this robustly.

To that end, fix the intel_map_sg() path to line up the mapping
correctly (in units of MM pages rather than VT-d pages to match the
aligned_nrpages() calculation) regardless of the offset, and use
sg_phys() consistently for clarity.

Reported-by: Harsh Jain <Harsh@chelsio.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/intel-iommu.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 6784a05dd6b2..83f3d4831f94 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2254,10 +2254,12 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
 		uint64_t tmp;
 
 		if (!sg_res) {
+			unsigned int pgoff = sg->offset & ~PAGE_MASK;
+
 			sg_res = aligned_nrpages(sg->offset, sg->length);
-			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
+			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
 			sg->dma_length = sg->length;
-			pteval = page_to_phys(sg_page(sg)) | prot;
+			pteval = (sg_phys(sg) - pgoff) | prot;
 			phys_pfn = pteval >> VTD_PAGE_SHIFT;
 		}
 
@@ -3790,7 +3792,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 
 	for_each_sg(sglist, sg, nelems, i) {
 		BUG_ON(!sg_page(sg));
-		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
+		sg->dma_address = sg_phys(sg);
 		sg->dma_length = sg->length;
 	}
 	return nelems;
-- 
2.13.4.dirty

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

end of thread, other threads:[~2017-11-17 18:09 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-28 14:14 [PATCH] iommu/vt-d: Fix scatterlist offset handling Robin Murphy
2017-09-28 16:17 ` Casey Leedom
2017-09-28 13:29   ` Raj, Ashok
2017-09-28 16:59     ` Robin Murphy
2017-09-28 15:43       ` Raj, Ashok
2017-10-03 19:36         ` Raj, Ashok
2017-09-29  8:14 ` Harsh Jain
     [not found]   ` <fe25071a-18bf-e468-01e7-36515f2110e2-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
2017-09-29 16:18     ` Casey Leedom
2017-09-29 16:18       ` Casey Leedom
     [not found]       ` <MWHPR12MB160034E91A834504FE85C07BC87E0-Gy0DoCVfaSVsWITs4OkDoAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-10-03 12:22         ` Harsh Jain
2017-10-03 22:22           ` Casey Leedom
     [not found] ` <644c3e01654f8bd48d669c36e424959d6ef0e27e.1506607370.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>
2017-10-03 12:55   ` David Woodhouse
2017-10-03 12:55     ` David Woodhouse
2017-10-03 18:05     ` Robin Murphy
2017-10-03 22:16       ` David Woodhouse
2017-10-04 11:18         ` Robin Murphy
2017-10-06 14:43       ` Joerg Roedel
2017-10-06 12:54         ` Raj, Ashok
     [not found]         ` <20171006144309.GA30803-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2017-11-06 18:47           ` Jacob Pan
2017-11-06 18:47             ` Jacob Pan
2017-11-15 23:54             ` Jacob Pan
2017-11-15 23:54               ` Jacob Pan
2017-11-16 21:32               ` Alex Williamson
     [not found]                 ` <20171116143244.2583d044-1yVPhWWZRC1BDLzU/O5InQ@public.gmane.org>
2017-11-16 21:09                   ` Raj, Ashok
2017-11-16 21:09                     ` Raj, Ashok
2017-11-17 16:18                     ` Alex Williamson
2017-11-17 16:18                       ` Alex Williamson
2017-11-17 15:48                       ` Raj, Ashok
2017-11-17 17:44                         ` Casey Leedom
2017-11-17 17:44                           ` Casey Leedom
2017-11-17 17:44                           ` Casey Leedom
     [not found]                           ` <SN1PR12MB035214EF471935B6F4220E36C82F0-z7L1TMIYDg4e2a8M8f4RFAdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-11-17 18:09                             ` Jacob Pan
2017-11-17 18:09                               ` Jacob Pan

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.