lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 311/530] RDMA/siw: Fix QP destroy to wait for all references dropped.
    Date
    From: Bernard Metzler <bmt@zurich.ibm.com>

    [ Upstream commit a3c278807a459e6f50afee6971cabe74cccfb490 ]

    Delay QP destroy completion until all siw references to QP are
    dropped. The calling RDMA core will free QP structure after
    successful return from siw_qp_destroy() call, so siw must not
    hold any remaining reference to the QP upon return.
    A use-after-free was encountered in xfstest generic/460, while
    testing NFSoRDMA. Here, after a TCP connection drop by peer,
    the triggered siw_cm_work_handler got delayed until after
    QP destroy call, referencing a QP which has already freed.

    Fixes: 303ae1cdfdf7 ("rdma/siw: application interface")
    Reported-by: Olga Kornievskaia <kolga@netapp.com>
    Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com>
    Link: https://lore.kernel.org/r/20220920082503.224189-1-bmt@zurich.ibm.com
    Signed-off-by: Leon Romanovsky <leon@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/infiniband/sw/siw/siw.h | 1 +
    drivers/infiniband/sw/siw/siw_qp.c | 2 +-
    drivers/infiniband/sw/siw/siw_verbs.c | 3 +++
    3 files changed, 5 insertions(+), 1 deletion(-)

    diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h
    index df03d84c6868..2f3a9cda3850 100644
    --- a/drivers/infiniband/sw/siw/siw.h
    +++ b/drivers/infiniband/sw/siw/siw.h
    @@ -418,6 +418,7 @@ struct siw_qp {
    struct ib_qp base_qp;
    struct siw_device *sdev;
    struct kref ref;
    + struct completion qp_free;
    struct list_head devq;
    int tx_cpu;
    struct siw_qp_attrs attrs;
    diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c
    index 7e01f2438afc..e6f634971228 100644
    --- a/drivers/infiniband/sw/siw/siw_qp.c
    +++ b/drivers/infiniband/sw/siw/siw_qp.c
    @@ -1342,6 +1342,6 @@ void siw_free_qp(struct kref *ref)
    vfree(qp->orq);

    siw_put_tx_cpu(qp->tx_cpu);
    -
    + complete(&qp->qp_free);
    atomic_dec(&sdev->num_qp);
    }
    diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
    index aa3f60d54a70..ff33659acffa 100644
    --- a/drivers/infiniband/sw/siw/siw_verbs.c
    +++ b/drivers/infiniband/sw/siw/siw_verbs.c
    @@ -478,6 +478,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
    list_add_tail(&qp->devq, &sdev->qp_list);
    spin_unlock_irqrestore(&sdev->lock, flags);

    + init_completion(&qp->qp_free);
    +
    return 0;

    err_out_xa:
    @@ -622,6 +624,7 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
    qp->scq = qp->rcq = NULL;

    siw_qp_put(qp);
    + wait_for_completion(&qp->qp_free);

    return 0;
    }
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-10-24 16:09    [W:4.095 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site