Sashiko points out that hns_roce_qp_remove() requires the caller to hold
locks.  The error flow in hns_roce_create_qp_common() doesn't hold those
locks for the error unwind so it risks corrupting memory.

Grab the same locks the other two callers use.

Cc: [email protected]
Fixes: e088a685eae9 ("RDMA/hns: Support rq record doorbell for the user space")
Link: 
https://sashiko.dev/#/patchset/0-v2-1c49eeb88c48%2B91-rdma_udata_rep_jgg%40nvidia.com?part=9
Signed-off-by: Jason Gunthorpe <[email protected]>
---
 drivers/infiniband/hw/hns/hns_roce_qp.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c 
b/drivers/infiniband/hw/hns/hns_roce_qp.c
index f94ba98871f0d0..bf04ee84a94392 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -1171,6 +1171,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev 
*hr_dev,
        struct hns_roce_ib_create_qp_resp resp = {};
        struct ib_device *ibdev = &hr_dev->ib_dev;
        struct hns_roce_ib_create_qp ucmd = {};
+       unsigned long flags;
        int ret;
 
        mutex_init(&hr_qp->mutex);
@@ -1257,7 +1258,13 @@ static int hns_roce_create_qp_common(struct hns_roce_dev 
*hr_dev,
        return 0;
 
 err_flow_ctrl:
+       spin_lock_irqsave(&hr_dev->qp_list_lock, flags);
+       hns_roce_lock_cqs(init_attr->send_cq ? to_hr_cq(init_attr->send_cq) : 
NULL,
+                         init_attr->recv_cq ? to_hr_cq(init_attr->recv_cq) : 
NULL);
        hns_roce_qp_remove(hr_dev, hr_qp);
+       hns_roce_unlock_cqs(init_attr->send_cq ? to_hr_cq(init_attr->send_cq) : 
NULL,
+                           init_attr->recv_cq ? to_hr_cq(init_attr->recv_cq) : 
NULL);
+       spin_unlock_irqrestore(&hr_dev->qp_list_lock, flags);
 err_store:
        free_qpc(hr_dev, hr_qp);
 err_qpc:
-- 
2.43.0


Reply via email to