Skip to content

Commit

Permalink
RDMA/siw: Fix QP destroy to wait for all references dropped.
Browse files Browse the repository at this point in the history
[ Upstream commit a3c2788 ]

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: 303ae1c ("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>
  • Loading branch information
BernardMetzler authored and gregkh committed Oct 21, 2022
1 parent 7fada7c commit 0ed8bf9
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/infiniband/sw/siw/siw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/sw/siw/siw_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
3 changes: 3 additions & 0 deletions drivers/infiniband/sw/siw/siw_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,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:
Expand Down Expand Up @@ -624,6 +626,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;
}
Expand Down

0 comments on commit 0ed8bf9

Please sign in to comment.