Various bug fixes for RDMA drivers in the uapi functions
Subsystems (13)
Jason Gunthorpe
maintainercover Various bug fixes for RDMA drivers in the uapi functions
All were found by Sashiko or Claude AI tools. They vary in severity, but are all things that shouldn't be present.
Jason Gunthorpe (15):
RDMA/ionic: Fix typo in format string
RDMA/mlx5: Restore zero-init to mlx5_ib_modify_qp() ucmd RDMA/mlx5: Add missing store/release for lock elision pattern RDMA/mana: Validate rx_hash_key_len
RDMA/mana: Remove user triggerable WARN_ON() in
mana_ib_create_qp_rss()
RDMA/mana: Fix mana_destroy_wq_obj() cleanup in
mana_ib_create_qp_rss() RDMA/mana: Fix error unwind in mana_ib_create_qp_rss() RDMA/ocrdma: Clarify the mm_head searching
RDMA/ocrdma: Don't NULL deref uctx on errors in ocrdma_copy_pd_uresp() RDMA/vmw_pvrdma: Fix double free on pvrdma_alloc_ucontext() error path RDMA/mlx4: Fix resource leak on error in mlx4_ib_create_srq() RDMA/mlx4: Fix mis-use of RCU in mlx4_srq_event() RDMA/hns: Fix xarray race in hns_roce_create_srq() RDMA/hns: Fix xarray race in hns_roce_create_qp_common() RDMA/hns: Fix unlocked call to hns_roce_qp_remove()
drivers/infiniband/hw/hns/hns_roce_qp.c | 13 ++++++++++--- drivers/infiniband/hw/hns/hns_roce_srq.c | 12 ++++++------ drivers/infiniband/hw/ionic/ionic_ibdev.c | 2 +- drivers/infiniband/hw/mana/cq.c | 5 +++-- drivers/infiniband/hw/mana/qp.c | 16 ++++++++++------ drivers/infiniband/hw/mlx4/srq.c | 4 +++- drivers/infiniband/hw/mlx5/main.c | 8 ++++---- drivers/infiniband/hw/mlx5/qp.c | 2 +- drivers/infiniband/hw/mlx5/umr.c | 4 ++-- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 ++++---- drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 2 +- drivers/net/ethernet/mellanox/mlx4/srq.c | 13 +++++++------ 12 files changed, 52 insertions(+), 37 deletions(-)
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 1/15 RDMA/ionic: Fix typo in format string
Applying the corrupted patch by hand mangled the format string, put the s in the right place.
--- drivers/infiniband/hw/ionic/ionic_ibdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/ionic/ionic_ibdev.c +1 -1
@@ -185,7 +185,7 @@ static ssize_t hca_type_show(struct device *device,struct ionic_ibdev *dev = rdma_device_to_drv_device(device, struct ionic_ibdev, ibdev); -return sysfs_emit (buf,"%s.64\n" , dev->ibdev.node_desc); +return sysfs_emit (buf,"%.64s\n" , dev->ibdev.node_desc); }static DEVICE_ATTR_RO (hca_type);
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 2/15 RDMA/mlx5: Restore zero-init to mlx5_ib_modify_qp() ucmd
In reply to Jason GunthorpeSashiko points out the check for inlen==0 got missed, the ={} was not redundant, put it back.
--- drivers/infiniband/hw/mlx5/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/qp.c +1 -1
@@ -4692,7 +4692,7 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,struct mlx5_ib_dev *dev =to_mdev (ibqp->device);struct mlx5_ib_modify_qp_resp resp = {};struct mlx5_ib_qp *qp =to_mqp (ibqp); -struct mlx5_ib_modify_qp ucmd; +struct mlx5_ib_modify_qp ucmd = {};enum ib_qp_type qp_type;enum ib_qp_state cur_state, new_state;int err = -EINVAL ;
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 3/15 RDMA/mlx5: Add missing store/release for lock elision pattern
In reply to Jason Gunthorpemlx5 has a common pattern implementing a device-global singleton resource where it checks the resource pointer for !NULL and then skips obtaining the lock.
This is not ordered properly as observing !NULL doesn't mean that all the data under that pointer is also visible on this CPU when the lock is not taken.
Use a release/acquire pairing to explicitly manage this.
Pointed out by sashiko, Codex found more cases.
--- drivers/infiniband/hw/mlx5/main.c | 8 ++++---- drivers/infiniband/hw/mlx5/umr.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/infiniband/hw/mlx5/main.c +4 -4
@@ -3310,7 +3310,7 @@ int mlx5_ib_dev_res_cq_init(struct mlx5_ib_dev *dev)* devr->c0 is set once, never changed until device unload. * Avoid taking the mutex if initialization is already done. */ -if (devr->c0) +if (smp_load_acquire (&devr->c0))return 0 ;mutex_lock (&devr->cq_lock);
@@ -3336,7 +3336,7 @@ int mlx5_ib_dev_res_cq_init(struct mlx5_ib_dev *dev) } devr->p0 = pd; - devr->c0 = cq; +smp_store_release (&devr->c0, cq); unlock:mutex_unlock (&devr->cq_lock);
@@ -3354,7 +3354,7 @@ int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev)* devr->s1 is set once, never changed until device unload. * Avoid taking the mutex if initialization is already done. */ -if (devr->s1) +if (smp_load_acquire (&devr->s1))return 0 ;mutex_lock (&devr->srq_lock);
@@ -3395,7 +3395,7 @@ int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev) } devr->s0 = s0; - devr->s1 = s1; +smp_store_release (&devr->s1, s1); unlock:mutex_unlock (&devr->srq_lock);
drivers/infiniband/hw/mlx5/umr.c +2 -2
@@ -147,7 +147,7 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)* UMR qp is set once, never changed until device unload. * Avoid taking the mutex if initialization is already done. */ -if (dev->umrc.qp) +if (smp_load_acquire (&dev->umrc.qp))return 0 ;mutex_lock (&dev->umrc.init_lock);
@@ -185,7 +185,7 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)sema_init (&dev->umrc.sem,MAX_UMR_WR );mutex_init (&dev->umrc.lock); dev->umrc.state =MLX5_UMR_STATE_ACTIVE ; - dev->umrc.qp = qp; +smp_store_release (&dev->umrc.qp, qp);mutex_unlock (&dev->umrc.init_lock);return 0 ;
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 4/15 RDMA/mana: Validate rx_hash_key_len
In reply to Jason GunthorpeSashiko points out that rx_hash_key_len comes from a uAPI structure and is blindly passed to memcpy, allowing the userspace to trash kernel memory. Bounds check it so the memcpy cannot overflow.
--- drivers/infiniband/hw/mana/qp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/infiniband/hw/mana/qp.c +3 -0
@@ -21,6 +21,9 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, gc =mdev_to_gc (dev); +if (rx_hash_key_len >sizeof (req->hashkey)) +return -EINVAL ; + req_buf_size =struct_size (req, indir_tab,MANA_INDIRECT_TABLE_DEF_SIZE ); req =kzalloc (req_buf_size,GFP_KERNEL );if (!req)
Signature · 1 line
2.43.0
RE: [EXTERNAL] [PATCH rc 04/15] RDMA/mana: Validate rx_hash_key_len
Quoted 17 lines
Sashiko points out that
rx_hash_key_lencomes from a uAPI structure and is blindly passed to memcpy, allowing the userspace to trash kernel memory. Bounds check it so the memcpy cannot overflow.Fixes 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft AzureNetwork Adapter")
Link:
https://sashiko.d/
ev%2F%23%2Fpatchset%2F0-v2-1c49eeb88c48%252B91- rdma_udata_rep_jgg%2540nvidia.com%3Fpart%3D1&data=05%7C02%7Clongli% 40microsoft.com%7C12e76b7833a74fb98a8208dea541b8cd%7C72f988bf86f141 af91ab2d7cd011db47%7C1%7C0%7C639129898875053924%7CUnknown%7CT WFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4 zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=75tKj32YfU uN7KdnsW63AjlwgnSLt2KXz34EUbXp2wI%3D&reserved=0
Quoted 1 line
Signed-off-by Jason Gunthorpe <[email protected]>
Quoted 22 lines
--- drivers/infiniband/hw/mana/qp.c | 3 +++ 1 file changed, 3 insertions(+)drivers/infiniband/hw/mana/qp.c +3
-0@@ -21,6 +21,9 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, gc =mdev_to_gc (dev); +if (rx_hash_key_len >sizeof (req->hashkey)) +return -EINVAL ; + req_buf_size =struct_size (req, indir_tab,MANA_INDIRECT_TABLE_DEF_SIZE );req = kzalloc(req_buf_size, GFP_KERNEL); if (!req)--
2.43.0
Jason Gunthorpe
maintainerPATCH 5/15 RDMA/mana: Remove user triggerable WARN_ON() in mana_ib_create_qp_rss()
In reply to Jason GunthorpeSashiko points out that the user can specify WQs sharing the same CQ as a part of the uAPI and this will trigger the WARN_ON() then go on to corrupt the kernel.
Just reject it outright and fail the QP creation.
--- drivers/infiniband/hw/mana/cq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/hw/mana/cq.c +3 -2
@@ -137,8 +137,9 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq)if (cq->queue.id >= gc->max_num_cqs)return -EINVAL ; -/* Create CQ table entry */ -WARN_ON (gc->cq_table[cq->queue.id]); +/* Create CQ table entry, sharing a CQ between WQs is not supported */ +if (gc->cq_table[cq->queue.id]) +return -EINVAL ;if (cq->queue.kmem) gdma_cq = cq->queue.kmem;else
Signature · 1 line
2.43.0
RE: [EXTERNAL] [PATCH rc 05/15] RDMA/mana: Remove user triggerable WARN_ON() in mana_ib_create_qp_rss()
Quoted 17 lines
Sashiko points out that the user can specify WQs sharing the same CQ as a part of the uAPI and this will trigger the
WARN_ON()then go on to corrupt the kernel.Just reject it outright and fail the QP creation.
Fixes c15d7802a424 ("RDMA/mana_ib: Add CQ interrupt support for RAW QP")Link:
https://sashiko.d/
ev%2F%23%2Fpatchset%2F0-v2-1c49eeb88c48%252B91- rdma_udata_rep_jgg%2540nvidia.com%3Fpart%3D1&data=05%7C02%7Clongli% 40microsoft.com%7C05b55740f97741c63c8408dea541ba1a%7C72f988bf86f141 af91ab2d7cd011db47%7C1%7C0%7C639129898905286592%7CUnknown%7CT WFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4 zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=045NsQ2efi m0Mmc8EGeKWQ3pyFbs63%2B2023OvD3%2B8IM%3D&reserved=0
Quoted 1 line
Signed-off-by Jason Gunthorpe <[email protected]>
Quoted 23 lines
--- drivers/infiniband/hw/mana/cq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/infiniband/hw/mana/cq.c +3
-2@@ -137,8 +137,9 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq)if (cq->queue.id >= gc->max_num_cqs)return -EINVAL ; -/* Create CQ table entry */ -WARN_ON (gc->cq_table[cq->queue.id]); +/* Create CQ table entry, sharing a CQ between WQs is not supported */ +if (gc->cq_table[cq->queue.id]) +return -EINVAL ;if (cq->queue.kmem) gdma_cq = cq->queue.kmem;else
--
2.43.0
Jason Gunthorpe
maintainerPATCH 6/15 RDMA/mana: Fix mana_destroy_wq_obj() cleanup in mana_ib_create_qp_rss()
In reply to Jason GunthorpeSashiko points out there are two bugs here in the error unwind flow, both related to how the WQ table is unwound.
First there is a double i-- on the first failure path due to the while loop having a i--, remove it.
Second if mana_ib_install_cq_cb() fails then mana_create_wq_obj() is not undone due to the above i--.
--- drivers/infiniband/hw/mana/qp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/infiniband/hw/mana/qp.c +4 -5
@@ -176,11 +176,8 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, ret =mana_create_wq_obj (mpc, mpc->port_handle,GDMA_RQ , &wq_spec, &cq_spec, &wq->rx_object); -if (ret) { -/* Do cleanup starting with index i-1 */ - i--; +if (ret) goto fail; - }/* The GDMA regions are now owned by the WQ object */ wq->queue.gdma_region =GDMA_INVALID_DMA_REGION ;
@@ -200,8 +197,10 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,/* Create CQ table entry */ ret =mana_ib_install_cq_cb (mdev, cq); -if (ret) +if (ret) { +mana_destroy_wq_obj (mpc,GDMA_RQ , wq->rx_object); goto fail; + } } resp.num_entries = i;
Signature · 1 line
2.43.0
RE: [EXTERNAL] [PATCH rc 06/15] RDMA/mana: Fix mana_destroy_wq_obj() cleanup in mana_ib_create_qp_rss()
Quoted 21 lines
Sashiko points out there are two bugs here in the error unwind flow, both related to how the WQ table is unwound.
First there is a double i-- on the first failure path due to the while loop having a i--, remove it.
Second if
mana_ib_install_cq_cb()fails thenmana_create_wq_obj()is not undone due to the above i--.Fixes c15d7802a424 ("RDMA/mana_ib: Add CQ interrupt support for RAW QP")Link:
https://sashiko.d/
ev%2F%23%2Fpatchset%2F0-v2-1c49eeb88c48%252B91- rdma_udata_rep_jgg%2540nvidia.com%3Fpart%3D1&data=05%7C02%7Clongli% 40microsoft.com%7Cd4d57c89064d4cc1781e08dea541b72a%7C72f988bf86f141 af91ab2d7cd011db47%7C1%7C0%7C639129898849523924%7CUnknown%7CT WFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4 zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=hbczVL%2F QTqw5zawJJPpSNkjtDrBOJNkV5Qn9vGGYbhE%3D&reserved=0
Quoted 1 line
Signed-off-by Jason Gunthorpe <[email protected]>
Quoted 39 lines
--- drivers/infiniband/hw/mana/qp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)drivers/infiniband/hw/mana/qp.c +1
-4@@ -176,11 +176,8 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp,struct ib_pd *pd, ret =mana_create_wq_obj (mpc, mpc->port_handle,GDMA_RQ , &wq_spec, &cq_spec, &wq- >rx_object); -if (ret) { -/* Do cleanup starting with index i-1 */ - i--; +if (ret) goto fail; - }/* The GDMA regions are now owned by the WQ object */ wq->queue.gdma_region = GDMA_INVALID_DMA_REGION; @@-200,8 +197,10 @@ static int mana_ib_create_qp_rss(struct
ib_qp*ibqp, structib_pd*pd,/* Create CQ table entry */ ret = mana_ib_install_cq_cb(mdev, cq);drivers/infiniband/hw/mana/qp.c +2
-1-if (ret) +if (ret) { + mana_destroy_wq_obj(mpc, GDMA_RQ, wq-Quoted 1 line
rx_object);goto fail; + } } resp.num_entries = i;--
2.43.0
Jason Gunthorpe
maintainerPATCH 7/15 RDMA/mana: Fix error unwind in mana_ib_create_qp_rss()
In reply to Jason GunthorpeSashiko points out that mana_ib_cfg_vport_steering() is leaked, the normal destroy path cleans it up.
--- drivers/infiniband/hw/mana/qp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mana/qp.c +3 -1
@@ -217,13 +217,15 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,ibdev_dbg (&mdev->ib_dev,"Failed to copy to udata create rss-qp, %d\n" , ret); - goto fail; + goto err_disable_vport_rx; }kfree (mana_ind_table);return 0 ; +err_disable_vport_rx: +mana_disable_vport_rx (mpc); fail:while (i-- >0 ) { ibwq = ind_tbl->ind_tbl[i];
Signature · 1 line
2.43.0
RE: [EXTERNAL] [PATCH rc 07/15] RDMA/mana: Fix error unwind in mana_ib_create_qp_rss()
Quoted 16 lines
Sashiko points out that
mana_ib_cfg_vport_steering()is leaked, the normal destroy path cleans it up.Fixes 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft AzureNetwork Adapter")
Link:
https://sashiko.d/
ev%2F%23%2Fpatchset%2F0-v1-e911b76a94d1%252B65d95- rdma_udata_rep_jgg%2540nvidia.com%3Fpart%3D4&data=05%7C02%7Clongli% 40microsoft.com%7Cb377464abc954481e9b108dea541b646%7C72f988bf86f141 af91ab2d7cd011db47%7C1%7C0%7C639129898856785811%7CUnknown%7CT WFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4 zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=pqtgE8ULS pXgq%2BbpubumadArZO9lTvPki2ATvD9TnGI%3D&reserved=0
Quoted 1 line
Signed-off-by Jason Gunthorpe <[email protected]>
Quoted 28 lines
--- drivers/infiniband/hw/mana/qp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)drivers/infiniband/hw/mana/qp.c +3
-1@@ -217,13 +217,15 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, ibdev_dbg(&mdev->ib_dev,"Failed to copy to udata create rss-qp, %d\n" , ret); - goto fail; + goto err_disable_vport_rx; }kfree (mana_ind_table);return 0 ; +err_disable_vport_rx: +mana_disable_vport_rx (mpc); fail:while (i-- >0 ) {ibwq = ind_tbl->ind_tbl[i];--
2.43.0
Jason Gunthorpe
maintainerPATCH 8/15 RDMA/ocrdma: Clarify the mm_head searching
In reply to Jason GunthorpeThe intention of this code is to find matching entries exactly, the driver never creates phys_addr's with different lens so the current expression is not a bug, but it doesn't make sense and confuses review tooling.
Search for exact match instead.
--- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +2 -2
@@ -215,7 +215,7 @@ static void ocrdma_del_mmap(struct ocrdma_ucontext *uctx, u64 phy_addr,mutex_lock (&uctx->mm_list_lock);list_for_each_entry_safe (mm, tmp, &uctx->mm_head, entry) { -if (len != mm->key.len && phy_addr != mm->key.phy_addr) +if (len != mm->key.len || phy_addr != mm->key.phy_addr)continue ;list_del (&mm->entry);
@@ -233,7 +233,7 @@ static bool ocrdma_search_mmap(struct ocrdma_ucontext *uctx, u64 phy_addr,mutex_lock (&uctx->mm_list_lock);list_for_each_entry (mm, &uctx->mm_head, entry) { -if (len != mm->key.len && phy_addr != mm->key.phy_addr) +if (len != mm->key.len || phy_addr != mm->key.phy_addr)continue ; found = true;
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 9/15 RDMA/ocrdma: Don't NULL deref uctx on errors in ocrdma_copy_pd_uresp()
In reply to Jason GunthorpeSashiko points out that pd->uctx isn't initialized until late in the function so all these error flow references are NULL and will crash. Use the uctx that isn't NULL.
--- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +2 -2
@@ -620,9 +620,9 @@ static int ocrdma_copy_pd_uresp(struct ocrdma_dev *dev, struct ocrdma_pd *pd, ucopy_err:if (pd->dpp_enabled) -ocrdma_del_mmap (pd->uctx, dpp_page_addr,PAGE_SIZE ); +ocrdma_del_mmap (uctx, dpp_page_addr,PAGE_SIZE ); dpp_map_err: -ocrdma_del_mmap (pd->uctx, db_page_addr, db_page_size); +ocrdma_del_mmap (uctx, db_page_addr, db_page_size);return status; }
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 10/15 RDMA/vmw_pvrdma: Fix double free on pvrdma_alloc_ucontext() error path
In reply to Jason GunthorpeSashiko points out that pvrdma_uar_free() is already called within pvrdma_dealloc_ucontext(), so calling it before triggers a double free.
--- drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c +1 -1
@@ -322,7 +322,7 @@ int pvrdma_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata) uresp.qp_tab_size = vdev->dsr->caps.max_qp; ret =ib_copy_to_udata (udata, &uresp,sizeof (uresp));if (ret) { -pvrdma_uar_free (vdev, &context->uar); +/* pvrdma_dealloc_ucontext() also frees the UAR */ pvrdma_dealloc_ucontext (&context->ibucontext);return -EFAULT ; }
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 11/15 RDMA/mlx4: Fix resource leak on error in mlx4_ib_create_srq()
In reply to Jason GunthorpeSashiko points out that mlx4_srq_alloc() was not undone during error unwind, add the missing call to mlx4_srq_free().
--- drivers/infiniband/hw/mlx4/srq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx4/srq.c +3 -1
@@ -194,13 +194,15 @@ int mlx4_ib_create_srq(struct ib_srq *ib_srq,if (udata)if (ib_copy_to_udata (udata, &srq->msrq.srqn,sizeof (__u32))) { err = -EFAULT ; - goto err_wrid; + goto err_srq; } init_attr->attr.max_wr = srq->msrq.max -1 ;return 0 ; +err_srq: +mlx4_srq_free (dev->dev, &srq->msrq); err_wrid:if (udata)mlx4_ib_db_unmap_user (ucontext, &srq->db);
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 12/15 RDMA/mlx4: Fix mis-use of RCU in mlx4_srq_event()
In reply to Jason GunthorpeSashiko points out the radix_tree itself is RCU safe, but nothing ever frees the mlx4_srq struct with RCU, and it isn't even accessed within the RCU critical section. It also will crash if an event is delivered before the srq object is finished initializing.
Use the spinlock since it isn't easy to make RCU work, use refcount_inc_not_zero() to protect against partially initialized objects, and order the refcount_set() to be after the srq is fully initialized.
--- drivers/net/ethernet/mellanox/mlx4/srq.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/net/ethernet/mellanox/mlx4/srq.c +7 -6
@@ -44,13 +44,14 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) {struct mlx4_srq_table *srq_table = &mlx4_priv (dev)->srq_table;struct mlx4_srq *srq; +unsigned long flags; -rcu_read_lock (); +spin_lock_irqsave (&srq_table->lock, flags); srq =radix_tree_lookup (&srq_table->tree, srqn & (dev->caps.num_srqs -1 )); -rcu_read_unlock (); -if (srq) -refcount_inc (&srq->refcount); -else { +if (!srq || !refcount_inc_not_zero (&srq->refcount)) + srq =NULL ; +spin_unlock_irqrestore (&srq_table->lock, flags); +if (!srq) {mlx4_warn (dev,"Async event for bogus SRQ %08x\n" , srqn);return ; }
@@ -203,8 +204,8 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,if (err) goto err_radix; -refcount_set (&srq->refcount,1 );init_completion (&srq->free); +refcount_set_release (&srq->refcount,1 );return 0 ;
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 13/15 RDMA/hns: Fix xarray race in hns_roce_create_srq()
In reply to Jason GunthorpeSashiko points out that once the srq memory is stored into the xarray by alloc_srqc() it can immediately be looked up by:
xa_lock(&srq_table->xa); srq = xa_load(&srq_table->xa, srqn & (hr_dev->caps.num_srqs - 1)); if (srq) refcount_inc(&srq->refcount); xa_unlock(&srq_table->xa);
Which will fail refcount debug because the refcount is 0 and then crash:
srq->event(srq, event_type);
Because event is NULL.
Use refcount_inc_not_zero() instead to ensure a partially prepared srq is never retrieved from the event handler and fix the ordering of the initialization so refcount becomes 1 only after it is fully ready.
All the initialization must be done before calling free_srqc() since it depends on the completion and refcount.
--- drivers/infiniband/hw/hns/hns_roce_srq.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/infiniband/hw/hns/hns_roce_srq.c +6 -6
@@ -16,8 +16,8 @@ void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type)xa_lock (&srq_table->xa); srq =xa_load (&srq_table->xa, srqn & (hr_dev->caps.num_srqs -1 )); -if (srq) -refcount_inc (&srq->refcount); +if (srq && !refcount_inc_not_zero (&srq->refcount)) + srq =NULL ;xa_unlock (&srq_table->xa);if (!srq) {
@@ -470,6 +470,10 @@ int hns_roce_create_srq(struct ib_srq *ib_srq,if (ret) goto err_srqn; + srq->event = hns_roce_ib_srq_event; +init_completion (&srq->free); +refcount_set_release (&srq->refcount,1 ); +if (udata) { resp.cap_flags = srq->cap_flags; resp.srqn = srq->srqn;
@@ -480,10 +484,6 @@ int hns_roce_create_srq(struct ib_srq *ib_srq, } } - srq->event = hns_roce_ib_srq_event; -refcount_set (&srq->refcount,1 ); -init_completion (&srq->free); -return 0 ; err_srqc:
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 14/15 RDMA/hns: Fix xarray race in hns_roce_create_qp_common()
In reply to Jason GunthorpeSimilar to the SRQ case the hr_qp is stored in the xarray before it is fully initialized. Unlike the SRQ case the error unwinds do not wait for the completion so keep the refcount 0 until the function succeeds.
--- drivers/infiniband/hw/hns/hns_roce_qp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/infiniband/hw/hns/hns_roce_qp.c +3 -3
@@ -47,8 +47,8 @@ static struct hns_roce_qp *hns_roce_qp_lookup(struct hns_roce_dev *hr_dev,xa_lock_irqsave (&hr_dev->qp_table_xa, flags); qp =__hns_roce_qp_lookup (hr_dev, qpn); -if (qp) -refcount_inc (&qp->refcount); +if (qp && !refcount_inc_not_zero (&qp->refcount)) + qp =NULL ;xa_unlock_irqrestore (&hr_dev->qp_table_xa, flags);if (!qp)
@@ -1251,8 +1251,8 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev, hr_qp->ibqp.qp_num = hr_qp->qpn; hr_qp->event = hns_roce_ib_qp_event; -refcount_set (&hr_qp->refcount,1 );init_completion (&hr_qp->free); +refcount_set_release (&hr_qp->refcount,1 );return 0 ;
Signature · 1 line
2.43.0
Jason Gunthorpe
maintainerPATCH 15/15 RDMA/hns: Fix unlocked call to hns_roce_qp_remove()
In reply to Jason GunthorpeSashiko 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.
--- drivers/infiniband/hw/hns/hns_roce_qp.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/infiniband/hw/hns/hns_roce_qp.c +7 -0
@@ -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:
Signature · 1 line
2.43.0
Quoted 7 lines · Jason Gunthorpe
All were found by Sashiko or Claude AI tools. They vary in severity, but are all things that shouldn't be present.
Jason Gunthorpe (15):
RDMA/hns: Fix xarray race inhns_roce_create_srq()RDMA/hns: Fix xarray race inhns_roce_create_qp_common()RDMA/hns: Fix unlocked call tohns_roce_qp_remove()
For hns patches:
Thanks,
Junxian
Quoted 22 lines · Jason Gunthorpe
All were found by Sashiko or Claude AI tools. They vary in severity, but are all things that shouldn't be present.
Jason Gunthorpe (15):
RDMA/ionic: Fix typo in format string
RDMA/mlx5: Restore zero-init tomlx5_ib_modify_qp()ucmd RDMA/mlx5: Add missing store/release for lock elision pattern RDMA/mana: Validaterx_hash_key_len
RDMA/mana: Remove user triggerableWARN_ON()inmana_ib_create_qp_rss() RDMA/mana: Fix mana_destroy_wq_obj() cleanup in mana_ib_create_qp_rss()RDMA/mana: Fix error unwind in
mana_ib_create_qp_rss()RDMA/ocrdma: Clarify themm_headsearching
RDMA/ocrdma: Don't NULL deref uctx on errors inocrdma_copy_pd_uresp()RDMA/vmw_pvrdma: Fix double free onpvrdma_alloc_ucontext()error path RDMA/mlx4: Fix resource leak on error inmlx4_ib_create_srq()RDMA/mlx4: Fix mis-use of RCU inmlx4_srq_event()RDMA/hns: Fix xarray race inhns_roce_create_srq()RDMA/hns: Fix xarray race inhns_roce_create_qp_common()RDMA/hns: Fix unlocked call tohns_roce_qp_remove()
Quoted 13 lines
drivers/infiniband/hw/hns/hns_roce_qp.c | 13 ++++++++++--- drivers/infiniband/hw/hns/hns_roce_srq.c | 12 ++++++------ drivers/infiniband/hw/ionic/ionic_ibdev.c | 2 +- drivers/infiniband/hw/mana/cq.c | 5 +++-- drivers/infiniband/hw/mana/qp.c | 16 ++++++++++------ drivers/infiniband/hw/mlx4/srq.c | 4 +++- drivers/infiniband/hw/mlx5/main.c | 8 ++++---- drivers/infiniband/hw/mlx5/qp.c | 2 +- drivers/infiniband/hw/mlx5/umr.c | 4 ++-- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 ++++---- drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 2 +- drivers/net/ethernet/mellanox/mlx4/srq.c | 13 +++++++------ 12 files changed, 52 insertions(+), 37 deletions(-)
Applied to for-rc
Jason