From patchwork Tue Mar 3 11:51:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 230066 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10067C3F2CD for ; Tue, 3 Mar 2020 11:52:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D50ED20866 for ; Tue, 3 Mar 2020 11:52:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583236325; bh=bqw6gnhe8DaJUx8gH+mJ8ulDLAoF7VExRZOOBVm+YKs=; h=From:To:Cc:Subject:Date:List-ID:From; b=V8f6ByMh/HMcd+H5eF/tZ8SWN1yQQM2h3DgC8L/sgPTvJL2UuIE1Xe28RbdoZiR/p Kn3aEX53QUBm3Np7robeNhMwPLM5msIxGx7RAg14V3Zmz+xA5uLXWgErvLoxAvS5Ml rXv9FxzrzVRPQIx+ngl071rsqgQNk8kQqBAVtsQY= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728999AbgCCLwF (ORCPT ); Tue, 3 Mar 2020 06:52:05 -0500 Received: from mail.kernel.org ([198.145.29.99]:60268 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725818AbgCCLwF (ORCPT ); Tue, 3 Mar 2020 06:52:05 -0500 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3B87B206E6; Tue, 3 Mar 2020 11:52:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583236324; bh=bqw6gnhe8DaJUx8gH+mJ8ulDLAoF7VExRZOOBVm+YKs=; h=From:To:Cc:Subject:Date:From; b=JXF0uiz3jtCtvEfEVSqRNYIHGXTV5VZNnZ6EJWoeHcnrED/zkBjXc76Dram1Y0K5p m0MnsWtFgIg4xvHwJ4kC8++CU/FgIrZvv0NF6an83SPnbX5U95/g87cnuPyqKE05de GX98dfLrD4jns48F0p2vzD5A/5kYkpCqykMUKNrE= Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1j965i-009exf-61; Tue, 03 Mar 2020 11:52:02 +0000 From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Robin Murphy , Joerg Roedel , Eric Auger , Will Deacon , stable@vger.kernel.org Subject: [PATCH] iommu/dma: Fix MSI reservation allocation Date: Tue, 3 Mar 2020 11:51:54 +0000 Message-Id: <20200303115154.32263-1-maz@kernel.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, robin.murphy@arm.com, jroedel@suse.de, eric.auger@redhat.com, will@kernel.org, stable@vger.kernel.org X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org The way cookie_init_hw_msi_region() allocates the iommu_dma_msi_page structures doesn't match the way iommu_put_dma_cookie() frees them. The former performs a single allocation of all the required structures, while the latter tries to free them one at a time. It doesn't quite work for the main use case (the GICv3 ITS where the range is 64kB) when the base ganule size is 4kB. This leads to a nice slab corruption on teardown, which is easily observable by simply creating a VF on a SRIOV-capable device, and tearing it down immediately (no need to even make use of it). Fix it by allocating iommu_dma_msi_page structures one at a time. Fixes: 7c1b058c8b5a3 ("iommu/dma: Handle IOMMU API reserved regions") Signed-off-by: Marc Zyngier Cc: Robin Murphy Cc: Joerg Roedel Cc: Eric Auger Cc: Will Deacon Cc: stable@vger.kernel.org --- drivers/iommu/dma-iommu.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index a2e96a5fd9a7..01fa64856c12 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -171,25 +171,37 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, phys_addr_t start, phys_addr_t end) { struct iova_domain *iovad = &cookie->iovad; - struct iommu_dma_msi_page *msi_page; - int i, num_pages; + struct iommu_dma_msi_page *msi_page, *tmp; + int i, num_pages, ret = 0; + phys_addr_t base; - start -= iova_offset(iovad, start); + base = start -= iova_offset(iovad, start); num_pages = iova_align(iovad, end - start) >> iova_shift(iovad); - msi_page = kcalloc(num_pages, sizeof(*msi_page), GFP_KERNEL); - if (!msi_page) - return -ENOMEM; - for (i = 0; i < num_pages; i++) { - msi_page[i].phys = start; - msi_page[i].iova = start; - INIT_LIST_HEAD(&msi_page[i].list); - list_add(&msi_page[i].list, &cookie->msi_page_list); + msi_page = kmalloc(sizeof(*msi_page), GFP_KERNEL); + if (!msi_page) { + ret = -ENOMEM; + break; + } + msi_page->phys = start; + msi_page->iova = start; + INIT_LIST_HEAD(&msi_page->list); + list_add(&msi_page->list, &cookie->msi_page_list); start += iovad->granule; } - return 0; + if (ret) { + list_for_each_entry_safe(msi_page, tmp, + &cookie->msi_page_list, list) { + if (msi_page->phys >= base && msi_page->phys < start) { + list_del(&msi_page->list); + kfree(msi_page); + } + } + } + + return ret; } static int iova_reserve_pci_windows(struct pci_dev *dev,