From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr690135.outbound.protection.outlook.com ([40.107.69.135]:4506 "EHLO NAM04-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726922AbeIGFOK (ORCPT ); Fri, 7 Sep 2018 01:14:10 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Jean-Philippe Brucker , Will Deacon , Sasha Levin Subject: [PATCH AUTOSEL 4.18 05/88] iommu/io-pgtable-arm-v7s: Abort allocation when table address overflows the PTE Date: Fri, 7 Sep 2018 00:35:56 +0000 Message-ID: <20180907003547.57567-5-alexander.levin@microsoft.com> References: <20180907003547.57567-1-alexander.levin@microsoft.com> In-Reply-To: <20180907003547.57567-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Jean-Philippe Brucker [ Upstream commit 29859aeb8a6ea17ba207933a81b6b77b4d4df81a ] 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 Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/io-pgtable-arm-v7s.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-= arm-v7s.c index 50e3a9fcf43e..b5948ba6b3b3 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -192,6 +192,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, { struct io_pgtable_cfg *cfg =3D &data->iop.cfg; struct device *dev =3D cfg->iommu_dev; + phys_addr_t phys; dma_addr_t dma; size_t size =3D ARM_V7S_TABLE_SIZE(lvl); void *table =3D NULL; @@ -200,6 +201,10 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, table =3D (void *)__get_dma_pages(__GFP_ZERO, get_order(size)); else if (lvl =3D=3D 2) table =3D kmem_cache_zalloc(data->l2_tables, gfp | GFP_DMA); + phys =3D virt_to_phys(table); + if (phys !=3D (arm_v7s_iopte)phys) + /* Doesn't fit in PTE */ + goto out_free; if (table && !(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) { dma =3D dma_map_single(dev, table, size, DMA_TO_DEVICE); if (dma_mapping_error(dev, dma)) @@ -209,7 +214,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, * address directly, so if the DMA layer suggests otherwise by * translating or truncating them, that bodes very badly... */ - if (dma !=3D virt_to_phys(table)) + if (dma !=3D phys) goto out_unmap; } kmemleak_ignore(table); --=20 2.17.1