iommu/io-pgtable: Sanitise map/unmap addresses
It may be an egregious error to attempt to use addresses outside the range of the pagetable format, but that still doesn't mean we should merrily wreak havoc by silently mapping/unmapping whatever truncated portions of them might happen to correspond to real addresses. Add some up-front checks to sanitise our inputs so that buggy callers don't invite potential memory corruption. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
c54451a5e2
commit
7655739143
|
@ -479,6 +479,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
|
||||||
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
|
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
|
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
|
||||||
/*
|
/*
|
||||||
* Synchronise all PTE updates for the new mapping before there's
|
* Synchronise all PTE updates for the new mapping before there's
|
||||||
|
@ -659,6 +662,9 @@ static int arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
|
||||||
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
|
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
|
||||||
size_t unmapped;
|
size_t unmapped;
|
||||||
|
|
||||||
|
if (WARN_ON(upper_32_bits(iova)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
unmapped = __arm_v7s_unmap(data, iova, size, 1, data->pgd);
|
unmapped = __arm_v7s_unmap(data, iova, size, 1, data->pgd);
|
||||||
if (unmapped)
|
if (unmapped)
|
||||||
io_pgtable_tlb_sync(&data->iop);
|
io_pgtable_tlb_sync(&data->iop);
|
||||||
|
|
|
@ -452,6 +452,10 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
|
||||||
if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
|
if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) ||
|
||||||
|
paddr >= (1ULL << data->iop.cfg.oas)))
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
prot = arm_lpae_prot_to_pte(data, iommu_prot);
|
prot = arm_lpae_prot_to_pte(data, iommu_prot);
|
||||||
ret = __arm_lpae_map(data, iova, paddr, size, prot, lvl, ptep);
|
ret = __arm_lpae_map(data, iova, paddr, size, prot, lvl, ptep);
|
||||||
/*
|
/*
|
||||||
|
@ -610,6 +614,9 @@ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
|
||||||
arm_lpae_iopte *ptep = data->pgd;
|
arm_lpae_iopte *ptep = data->pgd;
|
||||||
int lvl = ARM_LPAE_START_LVL(data);
|
int lvl = ARM_LPAE_START_LVL(data);
|
||||||
|
|
||||||
|
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
unmapped = __arm_lpae_unmap(data, iova, size, lvl, ptep);
|
unmapped = __arm_lpae_unmap(data, iova, size, lvl, ptep);
|
||||||
if (unmapped)
|
if (unmapped)
|
||||||
io_pgtable_tlb_sync(&data->iop);
|
io_pgtable_tlb_sync(&data->iop);
|
||||||
|
|
Loading…
Reference in New Issue