mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
RDMA/irdma: Add refcounting to user ring MRs
Prevent userspace from deregistering the MRs that back QP/CQ/SRQ rings
by bumping the MR's refcount upon association.
Fixes: b48c24c2d7 ("RDMA/irdma: Implement device supported verb APIs")
Signed-off-by: Jacob Moroni <jmoroni@google.com>
Link: https://patch.msgid.link/20260618201458.875740-5-jmoroni@google.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
971e99623e
commit
f67d8a08f6
|
|
@ -1168,6 +1168,12 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
|
|||
iwqp->kqp.dma_mem.va = NULL;
|
||||
kfree(iwqp->kqp.sq_wrid_mem);
|
||||
kfree(iwqp->kqp.rq_wrid_mem);
|
||||
|
||||
if (iwqp->user_mode && iwqp->iwpbl) {
|
||||
struct irdma_mr *iwmr = iwqp->iwpbl->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -464,6 +464,9 @@ static struct irdma_pbl *irdma_get_pbl(unsigned long va,
|
|||
|
||||
list_for_each_entry (iwpbl, pbl_list, list) {
|
||||
if (iwpbl->user_base == va) {
|
||||
struct irdma_mr *iwmr = iwpbl->iwmr;
|
||||
|
||||
refcount_inc(&iwmr->user_ring_refs);
|
||||
list_del(&iwpbl->list);
|
||||
iwpbl->on_list = false;
|
||||
return iwpbl;
|
||||
|
|
@ -1881,6 +1884,11 @@ static void irdma_srq_free_rsrc(struct irdma_pci_f *rf, struct irdma_srq *iwsrq)
|
|||
dma_free_coherent(rf->sc_dev.hw->device, iwsrq->kmem.size,
|
||||
iwsrq->kmem.va, iwsrq->kmem.pa);
|
||||
iwsrq->kmem.va = NULL;
|
||||
} else {
|
||||
/* Not called in any failure path, so iwpbl is valid. */
|
||||
struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
|
||||
irdma_free_rsrc(rf, rf->allocated_srqs, srq->srq_uk.srq_id);
|
||||
|
|
@ -1903,6 +1911,21 @@ static void irdma_cq_free_rsrc(struct irdma_pci_f *rf, struct irdma_cq *iwcq)
|
|||
iwcq->kmem_shadow.size,
|
||||
iwcq->kmem_shadow.va, iwcq->kmem_shadow.pa);
|
||||
iwcq->kmem_shadow.va = NULL;
|
||||
} else {
|
||||
struct irdma_mr *iwmr;
|
||||
|
||||
/* May be called in a failure path before iwpbl is valid. */
|
||||
if (iwcq->iwpbl) {
|
||||
iwmr = iwcq->iwpbl->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
|
||||
if (iwcq->iwpbl_shadow) {
|
||||
iwmr = iwcq->iwpbl_shadow->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
}
|
||||
|
||||
irdma_free_rsrc(rf, rf->allocated_cqs, cq->cq_uk.cq_id);
|
||||
|
|
@ -2018,7 +2041,7 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
|
|||
struct irdma_modify_cq_info info = {};
|
||||
struct irdma_dma_mem kmem_buf;
|
||||
struct irdma_cq_mr *cqmr_buf;
|
||||
struct irdma_pbl *iwpbl_buf;
|
||||
struct irdma_pbl *iwpbl_buf = NULL;
|
||||
struct irdma_device *iwdev;
|
||||
struct irdma_pci_f *rf;
|
||||
struct irdma_cq_buf *cq_buf = NULL;
|
||||
|
|
@ -2129,11 +2152,19 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
|
|||
goto error;
|
||||
|
||||
spin_lock_irqsave(&iwcq->lock, flags);
|
||||
if (udata)
|
||||
if (udata) {
|
||||
struct irdma_pbl *old_iwpbl = iwcq->iwpbl;
|
||||
|
||||
/* Only update if the resize was successful. Otherwise, HW is
|
||||
* still pointing to the old PBL.
|
||||
*/
|
||||
iwcq->iwpbl = iwpbl_buf;
|
||||
if (old_iwpbl) {
|
||||
struct irdma_mr *old_iwmr = old_iwpbl->iwmr;
|
||||
|
||||
refcount_dec(&old_iwmr->user_ring_refs);
|
||||
}
|
||||
}
|
||||
if (cq_buf) {
|
||||
cq_buf->kmem_buf = iwcq->kmem;
|
||||
cq_buf->hw = dev->hw;
|
||||
|
|
@ -2149,6 +2180,11 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
|
|||
|
||||
return 0;
|
||||
error:
|
||||
if (iwpbl_buf) {
|
||||
struct irdma_mr *iwmr = iwpbl_buf->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
if (!udata) {
|
||||
dma_free_coherent(dev->hw->device, kmem_buf.size, kmem_buf.va,
|
||||
kmem_buf.pa);
|
||||
|
|
@ -2425,6 +2461,11 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
|
|||
dma_free_coherent(rf->hw.device, iwsrq->kmem.size,
|
||||
iwsrq->kmem.va, iwsrq->kmem.pa);
|
||||
free_rsrc:
|
||||
if (iwsrq->user_mode && iwsrq->iwpbl) {
|
||||
struct irdma_mr *iwmr = iwsrq->iwpbl->iwmr;
|
||||
|
||||
refcount_dec(&iwmr->user_ring_refs);
|
||||
}
|
||||
irdma_free_rsrc(rf, rf->allocated_srqs, iwsrq->srq_num);
|
||||
return err_code;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user