mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
iommu/dma: Catch scatterlist length overflows
It is possible, when a very large mapping uses only one
scatterlist, that padding overflows scatterlist's length field.
This results in:
1) silently wrapping the value
2) smaller than desired mappings produced by iommu_map_sg
3) leaving mapped bytes in memory (no iommu_unmap)
Address this issue by adding overflow detection for scatterlist
length field.
Fixes: 809eac54cd ("iommu/dma: Implement scatterlist segment merging")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Reviewed-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
parent
1ae140d0f2
commit
1c8f6308e5
|
|
@ -1478,6 +1478,11 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
|||
sg_dma_len(s) = s_length;
|
||||
s->offset -= s_iova_off;
|
||||
s_length = iova_align(iovad, s_length + s_iova_off);
|
||||
if (overflows_type(s_length, s->length)) {
|
||||
ret = -EOVERFLOW;
|
||||
|
||||
goto out_restore_sg;
|
||||
}
|
||||
s->length = s_length;
|
||||
|
||||
/*
|
||||
|
|
@ -1494,7 +1499,20 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
|||
* time through here (i.e. before it has a meaningful value).
|
||||
*/
|
||||
if (pad_len && pad_len < s_length - 1) {
|
||||
prev->length += pad_len;
|
||||
unsigned int new_prev_len;
|
||||
|
||||
/*
|
||||
* For large mappings spanning multiple GBs we
|
||||
* may not be able to fit all needed padding into
|
||||
* sg->length.
|
||||
*/
|
||||
if (check_add_overflow(prev->length, pad_len, &new_prev_len)) {
|
||||
ret = -EOVERFLOW;
|
||||
|
||||
goto out_restore_sg;
|
||||
}
|
||||
|
||||
prev->length = new_prev_len;
|
||||
iova_len += pad_len;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user