Skip to content

Commit 29859ae

Browse files
Jean-Philippe Bruckerwildea01
authored andcommitted
iommu/io-pgtable-arm-v7s: Abort allocation when table address overflows the PTE
When run on a 64-bit system in selftest, the v7s driver may obtain page table with physical addresses larger than 32-bit. Level-2 tables are 1KB and are are allocated with slab, which doesn't accept the GFP_DMA32 flag. Currently map() truncates the address written in the PTE, causing iova_to_phys() or unmap() to access invalid memory. Kasan reports it as a use-after-free. To avoid any nasty surprise, test if the physical address fits in a PTE before returning a new table. 32-bit systems, which are the main users of this page table format, shouldn't see any difference. Signed-off-by: Jean-Philippe Brucker <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent fac83d2 commit 29859ae

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

drivers/iommu/io-pgtable-arm-v7s.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
192192
{
193193
struct io_pgtable_cfg *cfg = &data->iop.cfg;
194194
struct device *dev = cfg->iommu_dev;
195+
phys_addr_t phys;
195196
dma_addr_t dma;
196197
size_t size = ARM_V7S_TABLE_SIZE(lvl);
197198
void *table = NULL;
@@ -200,6 +201,10 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
200201
table = (void *)__get_dma_pages(__GFP_ZERO, get_order(size));
201202
else if (lvl == 2)
202203
table = kmem_cache_zalloc(data->l2_tables, gfp | GFP_DMA);
204+
phys = virt_to_phys(table);
205+
if (phys != (arm_v7s_iopte)phys)
206+
/* Doesn't fit in PTE */
207+
goto out_free;
203208
if (table && !(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) {
204209
dma = dma_map_single(dev, table, size, DMA_TO_DEVICE);
205210
if (dma_mapping_error(dev, dma))
@@ -209,7 +214,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
209214
* address directly, so if the DMA layer suggests otherwise by
210215
* translating or truncating them, that bodes very badly...
211216
*/
212-
if (dma != virt_to_phys(table))
217+
if (dma != phys)
213218
goto out_unmap;
214219
}
215220
kmemleak_ignore(table);

0 commit comments

Comments
 (0)