From nobody Sat Jul 25 19:28:42 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F8B236AB5A; Tue, 14 Jul 2026 10:50:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784026222; cv=none; b=TImyy/4QbhGJoBSytpEZn6mp7yF0KN7EZIWfUoXl6dOp6+f54PrUyOlL99NvV5io+gIgtvnYEHmz28x85hMJwe1g53zY/fyjLO9W5Sb8jHkaO9QM9MNDZoW0Yd/i0MvJBH6MC2nfHTxtL/JjvIMCOOO5LQx0Vkfd5BXUgkUclTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784026222; c=relaxed/simple; bh=S1YKqLp+zeGdnEQ3DThuaaAsF/0SajHOAJfEczntfk8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=pMEsojLPagxNiLpUNV8XdIQDBojKUZQAfHWhqEz4o3EZrxXZTNa83IeBhErUcI+vAX/Rl/Be6TtFU3TkZJ6jejaIpjK7DtKJ9leK7+/vBImpm76W0PopZgGQ+Ft1vuN5ucZ57aVOWx+id+jcT5y+ntE9ewLIMAkvUk04AaMabNw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IdFSjpq+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IdFSjpq+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A673A1F00A3A; Tue, 14 Jul 2026 10:50:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784026221; bh=sK4Lf3daq48rlYKbsi/uuM4qX0fuldUxbAOruMByj2I=; h=From:To:Cc:Subject:Date; b=IdFSjpq+iZbUbigDKMuP/34OfriXJUoRXBzdFlyZgWSb+Lha3vC5R7ihceuUXBvfw 0HZsNyXFOshDYPza7vhp/x/mrei/vgtY7dKS6HqTam90SNoZ3VDRKi3zHiXvs1rrnY 4Vy9LFphnQgtxyjtvUZmsHRpjNszzCL5MUqZ53CewuIzT+JxyqvRg6ueVzfOmf9pSu 4dUATU6E7EN1opDEzI/85plo1+XvyePtVVFXP3u0pdaoKy73hMDbi3pE5/UtfuPvXt kzOSe3QHUcJD38KUjzttw/oypZFWpPiV5tZs65JnPfuIfZySKgUoxqP3nTUdk90ksQ JdZ6++i7SVBpQ== From: Leon Romanovsky To: Selvin Xavier , Kalesh AP , Jason Gunthorpe , Leon Romanovsky , Jacob Moroni Cc: linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH rdma-next v2] RDMA/bnxt_re: Validate udata before executing commands Date: Tue, 14 Jul 2026 13:50:00 +0300 Message-ID: <20260714-fix-destroy-no-udata-v2-1-734fdcf667d5@kernel.org> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Change-ID: 20260712-fix-destroy-no-udata-dfa990b985ea X-Mailer: b4 0.15-dev-18f8f Content-Transfer-Encoding: quoted-printable From: Leon Romanovsky The destroy callbacks currently zero the udata output after tearing down driver resources. If the userspace access fails, uverbs preserves the uobject and allows the destroy callback to run again, even though the driver resource has already been freed. Call ib_no_udata_io() before teardown so udata failures are detected while the resource is still intact, then return success after teardown completes. As part of this change, move ib_respond_empty_udata() to the start of the create and modify flows. While this is not strictly required for general create flows, as the core layer unwinds uobjects on failure, it is necessary for create AH. In _rdma_create_ah(), the HW object is otherwise leaked. Fixes: bed686d8dcd4 ("RDMA/bnxt_re: Use ib_respond_empty_udata()") Signed-off-by: Leon Romanovsky Acked-by: Selvin Xavier --- Jacob, Selvin I didn't add your tags, as this patch was slightly changed from the previous version. Thanks Changes in v2: - Changed create and modify paths too - Link to v1: https://patch.msgid.link/20260713-fix-destroy-no-udata-v1-0-f= cca2e34fd57@nvidia.com --- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 65 +++++++++++++++-------------= ---- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/= hw/bnxt_re/ib_verbs.c index 90138d64adee..adc693736769 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -694,7 +694,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_u= data *udata) struct bnxt_re_dev *rdev =3D pd->rdev; int ret; =20 - ret =3D ib_is_udata_in_empty(udata); + ret =3D ib_no_udata_io(udata); if (ret) return ret; =20 @@ -711,7 +711,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_u= data *udata) &pd->qplib_pd)) atomic_dec(&rdev->stats.res.pd_count); } - return ib_respond_empty_udata(udata); + return 0; } =20 int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) @@ -843,7 +843,7 @@ int bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_= ah_init_attr *init_attr, u8 nw_type; int rc; =20 - rc =3D ib_is_udata_in_empty(udata); + rc =3D ib_no_udata_io(udata); if (rc) return rc; =20 @@ -900,7 +900,7 @@ int bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_= ah_init_attr *init_attr, if (active_ahs > rdev->stats.res.ah_watermark) rdev->stats.res.ah_watermark =3D active_ahs; =20 - return ib_respond_empty_udata(udata); + return 0; } =20 int bnxt_re_query_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr) @@ -1014,7 +1014,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib= _udata *udata) unsigned int flags; int rc; =20 - rc =3D ib_is_udata_in_empty(udata); + rc =3D ib_no_udata_io(udata); if (rc) return rc; =20 @@ -1063,7 +1063,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib= _udata *udata) if (scq_nq !=3D rcq_nq) bnxt_re_synchronize_nq(rcq_nq); =20 - return ib_respond_empty_udata(udata); + return 0; } =20 static u8 __from_ib_qp_type(enum ib_qp_type type) @@ -2147,7 +2147,7 @@ int bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct= ib_udata *udata) struct bnxt_qplib_srq *qplib_srq =3D &srq->qplib_srq; int ret; =20 - ret =3D ib_is_udata_in_empty(udata); + ret =3D ib_no_udata_io(udata); if (ret) return ret; =20 @@ -2158,7 +2158,7 @@ int bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct= ib_udata *udata) free_page((unsigned long)srq->uctx_srq_page); ib_umem_release(srq->umem); atomic_dec(&rdev->stats.res.srq_count); - return ib_respond_empty_udata(udata); + return 0; } =20 static int bnxt_re_init_user_srq(struct bnxt_re_dev *rdev, @@ -2296,34 +2296,25 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struc= t ib_srq_attr *srq_attr, { struct bnxt_re_srq *srq =3D container_of(ib_srq, struct bnxt_re_srq, ib_srq); - struct bnxt_re_dev *rdev =3D srq->rdev; int ret; =20 - ret =3D ib_is_udata_in_empty(udata); + ret =3D ib_no_udata_io(udata); if (ret) return ret; =20 - switch (srq_attr_mask) { - case IB_SRQ_MAX_WR: - /* SRQ resize is not supported */ + if (srq_attr_mask !=3D IB_SRQ_LIMIT) return -EINVAL; - case IB_SRQ_LIMIT: - /* Change the SRQ threshold */ - if (srq_attr->srq_limit > srq->qplib_srq.max_wqe) - return -EINVAL; =20 - srq->qplib_srq.threshold =3D srq_attr->srq_limit; - bnxt_qplib_srq_arm_db(&srq->qplib_srq.dbinfo, srq->qplib_srq.threshold); - - /* On success, update the shadow */ - srq->srq_limit =3D srq_attr->srq_limit; - /* No need to Build and send response back to udata */ - return ib_respond_empty_udata(udata); - default: - ibdev_err(&rdev->ibdev, - "Unsupported srq_attr_mask 0x%x", srq_attr_mask); + if (srq_attr->srq_limit > srq->qplib_srq.max_wqe) return -EINVAL; - } + + srq->qplib_srq.threshold =3D srq_attr->srq_limit; + bnxt_qplib_srq_arm_db(&srq->qplib_srq.dbinfo, srq->qplib_srq.threshold); + + /* On success, update the shadow */ + srq->srq_limit =3D srq_attr->srq_limit; + /* No need to Build and send response back to udata */ + return 0; } =20 int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr) @@ -2436,7 +2427,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_= qp_attr *qp_attr, unsigned int flags; u8 nw_type; =20 - rc =3D ib_is_udata_in_empty(udata); + rc =3D ib_no_udata_io(udata); if (rc) return rc; =20 @@ -2688,7 +2679,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_= qp_attr *qp_attr, if (rc) return rc; } - return ib_respond_empty_udata(udata); + return 0; } =20 int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, @@ -3470,7 +3461,7 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib= _udata *udata) nq =3D cq->qplib_cq.nq; cctx =3D rdev->chip_ctx; =20 - ret =3D ib_is_udata_in_empty(udata); + ret =3D ib_no_udata_io(udata); if (ret) return ret; =20 @@ -3485,7 +3476,7 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib= _udata *udata) atomic_dec(&rdev->stats.res.cq_count); kfree(cq->cql); ib_umem_release(cq->umem); - return ib_respond_empty_udata(udata); + return 0; } =20 int bnxt_re_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_att= r *attr, @@ -3687,6 +3678,10 @@ int bnxt_re_resize_cq(struct ib_cq *ibcq, unsigned i= nt cqe, if (rc) goto fail; =20 + rc =3D ib_respond_empty_udata(udata); + if (rc) + goto fail; + cq->resize_umem =3D ib_umem_get_va(&rdev->ibdev, req.cq_va, entries * sizeof(struct cq_base), IB_ACCESS_LOCAL_WRITE); @@ -3716,7 +3711,7 @@ int bnxt_re_resize_cq(struct ib_cq *ibcq, unsigned in= t cqe, cq->ib_cq.cqe =3D cq->resize_cqe; atomic_inc(&rdev->stats.res.resize_count); =20 - return ib_respond_empty_udata(udata); + return 0; =20 fail: if (cq->resize_umem) { @@ -4448,7 +4443,7 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_u= data *udata) struct bnxt_re_dev *rdev =3D mr->rdev; int rc; =20 - rc =3D ib_is_udata_in_empty(udata); + rc =3D ib_no_udata_io(udata); if (rc) return rc; =20 @@ -4471,7 +4466,7 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_u= data *udata) atomic_dec(&rdev->stats.res.mr_count); if (rc) return rc; - return ib_respond_empty_udata(udata); + return 0; } =20 static int bnxt_re_set_page(struct ib_mr *ib_mr, u64 addr) --- base-commit: eeb9697db6c16d9bb2ce7b7ddf95aa20305aa9f2 change-id: 20260712-fix-destroy-no-udata-dfa990b985ea Best regards, -- =20 Leon Romanovsky