From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-sn1nam02on0111.outbound.protection.outlook.com ([104.47.36.111]:14488 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932728AbeDIAhF (ORCPT ); Sun, 8 Apr 2018 20:37:05 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Sebastian Ott , Martin Schwidefsky , Sasha Levin Subject: [PATCH AUTOSEL for 4.4 081/162] s390/pci: improve unreg_ioat error handling Date: Mon, 9 Apr 2018 00:28:42 +0000 Message-ID: <20180409002738.163941-81-alexander.levin@microsoft.com> References: <20180409002738.163941-1-alexander.levin@microsoft.com> In-Reply-To: <20180409002738.163941-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: Sebastian Ott [ Upstream commit 725708349172f00b86e2bac5c03de360b79aaf65 ] DMA tables are freed in zpci_dma_exit_device regardless of the return code of zpci_unregister_ioat. This could lead to a use after free. On the other hand during function hot-unplug, zpci_unregister_ioat will always fail since the function is already gone. So let zpci_unregister_ioat report success when the function is gone but don't cleanup the dma table when a function could still have it in access. Signed-off-by: Sebastian Ott Reviewed-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky Signed-off-by: Sasha Levin --- arch/s390/pci/pci.c | 19 ++++++++++++++----- arch/s390/pci/pci_dma.c | 4 +++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index d95bfffdcc2e..a23140fd666b 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -166,19 +166,28 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 = dmaas, struct mod_pci_args int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas, u64 base, u64 limit, u64 iota) { - struct mod_pci_args args =3D { base, limit, iota, 0 }; + u64 req =3D ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_REG_IOAT); + struct zpci_fib fib =3D {0}; + u8 status; =20 WARN_ON_ONCE(iota & 0x3fff); - args.iota |=3D ZPCI_IOTA_RTTO_FLAG; - return mod_pci(zdev, ZPCI_MOD_FC_REG_IOAT, dmaas, &args); + fib.pba =3D base; + fib.pal =3D limit; + fib.iota =3D iota | ZPCI_IOTA_RTTO_FLAG; + return zpci_mod_fc(req, &fib, &status) ? -EIO : 0; } =20 /* Modify PCI: Unregister I/O address translation parameters */ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas) { - struct mod_pci_args args =3D { 0, 0, 0, 0 }; + u64 req =3D ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_DEREG_IOAT); + struct zpci_fib fib =3D {0}; + u8 cc, status; =20 - return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args); + cc =3D zpci_mod_fc(req, &fib, &status); + if (cc =3D=3D 3) /* Function already gone. */ + cc =3D 0; + return cc ? -EIO : 0; } =20 /* Modify PCI: Set PCI function measurement parameters */ diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 4004e03267cd..49ff18f8cf99 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -503,7 +503,9 @@ void zpci_dma_exit_device(struct zpci_dev *zdev) */ WARN_ON(zdev->s390_domain); =20 - zpci_unregister_ioat(zdev, 0); + if (zpci_unregister_ioat(zdev, 0)) + return; + dma_cleanup_tables(zdev->dma_table); zdev->dma_table =3D NULL; vfree(zdev->iommu_bitmap); --=20 2.15.1