Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76557391 authored by Robin Murphy's avatar Robin Murphy Committed by Will Deacon
Browse files

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: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent c54451a5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -479,6 +479,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
	if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
		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);
	/*
	 * 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);
	size_t unmapped;

	if (WARN_ON(upper_32_bits(iova)))
		return 0;

	unmapped = __arm_v7s_unmap(data, iova, size, 1, data->pgd);
	if (unmapped)
		io_pgtable_tlb_sync(&data->iop);
+7 −0
Original line number Diff line number Diff line
@@ -452,6 +452,10 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
	if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
		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);
	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;
	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);
	if (unmapped)
		io_pgtable_tlb_sync(&data->iop);