> 
> From: Leon Romanovsky <[email protected]>
> 
> mana_table_store_ud_qp() publishes a QP at its send-queue id before
> inserting the receive-queue id, dropping the XArray lock between the two
> xa_insert_irq() calls. A concurrent completion handler can look up the QP
> and take a transient reference. When the second insertion fails, the rollback
> erased only the send-queue entry and returned, leaving both the initial table
> reference and the transient reference outstanding while RDMA core frees the
> QP, causing a use-after-free.
> 
> Drain the reference as normal destruction does: drop the initial reference
> and wait for qp->free, releasing the QP only after every concurrent lookup
> returns its reference.
> 
> Fixes: 8001e9257eca ("RDMA/mana_ib: extend mana QP table")
> Signed-off-by: Leon Romanovsky <[email protected]>

Reviewed-by: Long Li <[email protected]>


> ---
> Konstantin,
> 
> I saw this in one of the Sashiko runs, and I believe the AI is correct. The
> reference can be acquired through the GDMA_EQE_RNIC_QP_FATAL event.
> 
> Thanks
> ---
>  drivers/infiniband/hw/mana/qp.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/mana/qp.c
> b/drivers/infiniband/hw/mana/qp.c index b5ff07e34eb7..c52f3ec14032
> 100644
> --- a/drivers/infiniband/hw/mana/qp.c
> +++ b/drivers/infiniband/hw/mana/qp.c
> @@ -472,6 +472,12 @@ static void mana_table_remove_rc_qp(struct
> mana_ib_dev *mdev, struct mana_ib_qp
>       xa_erase_irq(&mdev->qp_table_wq, qp->ibqp.qp_num);  }
> 
> +static void mana_table_drain_qp_ref(struct mana_ib_qp *qp) {
> +     mana_put_qp_ref(qp);
> +     wait_for_completion(&qp->free);
> +}
> +
>  static int mana_table_store_ud_qp(struct mana_ib_dev *mdev, struct
> mana_ib_qp *qp)  {
>       u32 qids = qp->ud_qp.queues[MANA_UD_SEND_QUEUE].id |
> MANA_SENDQ_MASK; @@ -490,6 +496,7 @@ static int
> mana_table_store_ud_qp(struct mana_ib_dev *mdev, struct mana_ib_qp *q
> 
>  remove_sq:
>       xa_erase_irq(&mdev->qp_table_wq, qids);
> +     mana_table_drain_qp_ref(qp);
>       return err;
>  }
> 
> @@ -537,8 +544,7 @@ static void mana_table_remove_qp(struct
> mana_ib_dev *mdev,
>                         qp->ibqp.qp_type);
>               return;
>       }
> -     mana_put_qp_ref(qp);
> -     wait_for_completion(&qp->free);
> +     mana_table_drain_qp_ref(qp);
>  }
> 
>  static int mana_ib_create_rc_qp(struct ib_qp *ibqp, struct ib_pd *ibpd,
> 
> ---
> base-commit: 74f49255492a62658f36bf2578d7916f1c6ffad1
> change-id: 20260721-if-mana-table-store-qp-qids-partiall-afa14f023261
> 
> Best regards,
> --
> Leon Romanovsky <[email protected]>

Reply via email to