lkml.org 
[lkml]   [2018]   [Apr]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL for 4.4 081/162] s390/pci: improve unreg_ioat error handling
    Date
    From: Sebastian Ott <sebott@linux.vnet.ibm.com>

    [ 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 <sebott@linux.vnet.ibm.com>
    Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
    Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    ---
    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 = { base, limit, iota, 0 };
    + u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_REG_IOAT);
    + struct zpci_fib fib = {0};
    + u8 status;

    WARN_ON_ONCE(iota & 0x3fff);
    - args.iota |= ZPCI_IOTA_RTTO_FLAG;
    - return mod_pci(zdev, ZPCI_MOD_FC_REG_IOAT, dmaas, &args);
    + fib.pba = base;
    + fib.pal = limit;
    + fib.iota = iota | ZPCI_IOTA_RTTO_FLAG;
    + return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
    }

    /* Modify PCI: Unregister I/O address translation parameters */
    int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
    {
    - struct mod_pci_args args = { 0, 0, 0, 0 };
    + u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_DEREG_IOAT);
    + struct zpci_fib fib = {0};
    + u8 cc, status;

    - return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
    + cc = zpci_mod_fc(req, &fib, &status);
    + if (cc == 3) /* Function already gone. */
    + cc = 0;
    + return cc ? -EIO : 0;
    }

    /* 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);

    - zpci_unregister_ioat(zdev, 0);
    + if (zpci_unregister_ioat(zdev, 0))
    + return;
    +
    dma_cleanup_tables(zdev->dma_table);
    zdev->dma_table = NULL;
    vfree(zdev->iommu_bitmap);
    --
    2.15.1
    \
     
     \ /
      Last update: 2018-04-09 03:22    [W:2.348 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site