diff options
author | Robin Murphy <robin.murphy@arm.com> | 2017-09-28 15:14:01 +0100 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2017-11-17 10:28:58 -0700 |
commit | 29a90b70893817e2f2bb3cea40a29f5308e21b21 (patch) | |
tree | cec99a92048198794375665264267125dafb1bc1 /include/pcmcia | |
parent | cf9b0772f2e410645fece13b749bd56505b998b8 (diff) | |
download | linux-29a90b70893817e2f2bb3cea40a29f5308e21b21.tar.gz linux-29a90b70893817e2f2bb3cea40a29f5308e21b21.tar.bz2 linux-29a90b70893817e2f2bb3cea40a29f5308e21b21.zip |
iommu/vt-d: Fix scatterlist offset handling
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>
Reviewed by: Ashok Raj <ashok.raj@intel.com>
Tested by: Jacob Pan <jacob.jun.pan@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'include/pcmcia')
0 files changed, 0 insertions, 0 deletions