]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject()
authorMaher Sanalla <msanalla@nvidia.com>
Wed, 26 Feb 2025 13:54:13 +0000 (15:54 +0200)
committerLeon Romanovsky <leon@kernel.org>
Thu, 13 Mar 2025 12:26:37 +0000 (08:26 -0400)
Currently, the IB uverbs API calls uobj_get_uobj_read(), which in turn
uses the rdma_lookup_get_uobject() helper to retrieve user objects.
In case of failure, uobj_get_uobj_read() returns NULL, overriding the
error code from rdma_lookup_get_uobject(). The IB uverbs API then
translates this NULL to -EINVAL, masking the actual error and
complicating debugging. For example, applications calling ibv_modify_qp
that fails with EBUSY when retrieving the QP uobject will see the
overridden error code EINVAL instead, masking the actual error.

Furthermore, based on rdma-core commit:
"2a22f1ced5f3 ("Merge pull request #1568 from jakemoroni/master")"
Kernel's IB uverbs return values are either ignored and passed on as is
to application or overridden with other errnos in a few cases.

Thus, to improve error reporting and debuggability, propagate the
original error from rdma_lookup_get_uobject() instead of replacing it
with EINVAL.

Signed-off-by: Maher Sanalla <msanalla@nvidia.com>
Link: https://patch.msgid.link/64f9d3711b183984e939962c2f83383904f97dfb.1740577869.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/uverbs_cmd.c
include/rdma/uverbs_std_types.h

index 96d639e1ffa014c1fa51469c8a91ef5216195b0f..3c3bb670c805c9498f88b36bf30c6fb50b2a129e 100644 (file)
@@ -735,8 +735,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
                goto err_free;
 
        pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
-       if (!pd) {
-               ret = -EINVAL;
+       if (IS_ERR(pd)) {
+               ret = PTR_ERR(pd);
                goto err_free;
        }
 
@@ -826,8 +826,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
        if (cmd.flags & IB_MR_REREG_PD) {
                new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle,
                                           attrs);
-               if (!new_pd) {
-                       ret = -EINVAL;
+               if (IS_ERR(new_pd)) {
+                       ret = PTR_ERR(new_pd);
                        goto put_uobjs;
                }
        } else {
@@ -936,8 +936,8 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs)
                return PTR_ERR(uobj);
 
        pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
-       if (!pd) {
-               ret = -EINVAL;
+       if (IS_ERR(pd)) {
+               ret = PTR_ERR(pd);
                goto err_free;
        }
 
@@ -1144,8 +1144,8 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs)
                return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
-       if (!cq)
-               return -EINVAL;
+       if (IS_ERR(cq))
+               return PTR_ERR(cq);
 
        ret = cq->device->ops.resize_cq(cq, cmd.cqe, &attrs->driver_udata);
        if (ret)
@@ -1206,8 +1206,8 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
                return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
-       if (!cq)
-               return -EINVAL;
+       if (IS_ERR(cq))
+               return PTR_ERR(cq);
 
        /* we copy a struct ib_uverbs_poll_cq_resp to user space */
        header_ptr = attrs->ucore.outbuf;
@@ -1255,8 +1255,8 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs)
                return ret;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
-       if (!cq)
-               return -EINVAL;
+       if (IS_ERR(cq))
+               return PTR_ERR(cq);
 
        ib_req_notify_cq(cq, cmd.solicited_only ?
                         IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
@@ -1338,8 +1338,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
                ind_tbl = uobj_get_obj_read(rwq_ind_table,
                                            UVERBS_OBJECT_RWQ_IND_TBL,
                                            cmd->rwq_ind_tbl_handle, attrs);
-               if (!ind_tbl) {
-                       ret = -EINVAL;
+               if (IS_ERR(ind_tbl)) {
+                       ret = PTR_ERR(ind_tbl);
                        goto err_put;
                }
 
@@ -1377,8 +1377,10 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
                        if (cmd->is_srq) {
                                srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ,
                                                        cmd->srq_handle, attrs);
-                               if (!srq || srq->srq_type == IB_SRQT_XRC) {
-                                       ret = -EINVAL;
+                               if (IS_ERR(srq) ||
+                                   srq->srq_type == IB_SRQT_XRC) {
+                                       ret = IS_ERR(srq) ? PTR_ERR(srq) :
+                                                                 -EINVAL;
                                        goto err_put;
                                }
                        }
@@ -1388,23 +1390,29 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
                                        rcq = uobj_get_obj_read(
                                                cq, UVERBS_OBJECT_CQ,
                                                cmd->recv_cq_handle, attrs);
-                                       if (!rcq) {
-                                               ret = -EINVAL;
+                                       if (IS_ERR(rcq)) {
+                                               ret = PTR_ERR(rcq);
                                                goto err_put;
                                        }
                                }
                        }
                }
 
-               if (has_sq)
+               if (has_sq) {
                        scq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
                                                cmd->send_cq_handle, attrs);
+                       if (IS_ERR(scq)) {
+                               ret = PTR_ERR(scq);
+                               goto err_put;
+                       }
+               }
+
                if (!ind_tbl && cmd->qp_type != IB_QPT_XRC_INI)
                        rcq = rcq ?: scq;
                pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle,
                                       attrs);
-               if (!pd || (!scq && has_sq)) {
-                       ret = -EINVAL;
+               if (IS_ERR(pd)) {
+                       ret = PTR_ERR(pd);
                        goto err_put;
                }
 
@@ -1499,18 +1507,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 err_put:
        if (!IS_ERR(xrcd_uobj))
                uobj_put_read(xrcd_uobj);
-       if (pd)
+       if (!IS_ERR_OR_NULL(pd))
                uobj_put_obj_read(pd);
-       if (scq)
+       if (!IS_ERR_OR_NULL(scq))
                rdma_lookup_put_uobject(&scq->uobject->uevent.uobject,
                                        UVERBS_LOOKUP_READ);
-       if (rcq && rcq != scq)
+       if (!IS_ERR_OR_NULL(rcq) && rcq != scq)
                rdma_lookup_put_uobject(&rcq->uobject->uevent.uobject,
                                        UVERBS_LOOKUP_READ);
-       if (srq)
+       if (!IS_ERR_OR_NULL(srq))
                rdma_lookup_put_uobject(&srq->uobject->uevent.uobject,
                                        UVERBS_LOOKUP_READ);
-       if (ind_tbl)
+       if (!IS_ERR_OR_NULL(ind_tbl))
                uobj_put_obj_read(ind_tbl);
 
        uobj_alloc_abort(&obj->uevent.uobject, attrs);
@@ -1672,8 +1680,8 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs)
        }
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp) {
-               ret = -EINVAL;
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
                goto out;
        }
 
@@ -1778,8 +1786,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs,
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd->base.qp_handle,
                               attrs);
-       if (!qp) {
-               ret = -EINVAL;
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
                goto out;
        }
 
@@ -2045,8 +2053,8 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
                return -ENOMEM;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp) {
-               ret = -EINVAL;
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
                goto out;
        }
 
@@ -2083,9 +2091,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
 
                        ud->ah = uobj_get_obj_read(ah, UVERBS_OBJECT_AH,
                                                   user_wr->wr.ud.ah, attrs);
-                       if (!ud->ah) {
+                       if (IS_ERR(ud->ah)) {
+                               ret = PTR_ERR(ud->ah);
                                kfree(ud);
-                               ret = -EINVAL;
                                goto out_put;
                        }
                        ud->remote_qpn = user_wr->wr.ud.remote_qpn;
@@ -2322,8 +2330,8 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs)
                return PTR_ERR(wr);
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp) {
-               ret = -EINVAL;
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
                goto out;
        }
 
@@ -2373,8 +2381,8 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs)
                return PTR_ERR(wr);
 
        srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
-       if (!srq) {
-               ret = -EINVAL;
+       if (IS_ERR(srq)) {
+               ret = PTR_ERR(srq);
                goto out;
        }
 
@@ -2430,8 +2438,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
        }
 
        pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
-       if (!pd) {
-               ret = -EINVAL;
+       if (IS_ERR(pd)) {
+               ret = PTR_ERR(pd);
                goto err;
        }
 
@@ -2500,8 +2508,8 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs)
                return ret;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp)
-               return -EINVAL;
+       if (IS_ERR(qp))
+               return PTR_ERR(qp);
 
        obj = qp->uobject;
 
@@ -2550,8 +2558,8 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs)
                return ret;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp)
-               return -EINVAL;
+       if (IS_ERR(qp))
+               return PTR_ERR(qp);
 
        obj = qp->uobject;
        mutex_lock(&obj->mcast_lock);
@@ -2685,8 +2693,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
                                                        UVERBS_OBJECT_FLOW_ACTION,
                                                        kern_spec->action.handle,
                                                        attrs);
-               if (!ib_spec->action.act)
-                       return -EINVAL;
+               if (IS_ERR(ib_spec->action.act))
+                       return PTR_ERR(ib_spec->action.act);
                ib_spec->action.size =
                        sizeof(struct ib_flow_spec_action_handle);
                flow_resources_add(uflow_res,
@@ -2703,8 +2711,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
                                          UVERBS_OBJECT_COUNTERS,
                                          kern_spec->flow_count.handle,
                                          attrs);
-               if (!ib_spec->flow_count.counters)
-                       return -EINVAL;
+               if (IS_ERR(ib_spec->flow_count.counters))
+                       return PTR_ERR(ib_spec->flow_count.counters);
                ib_spec->flow_count.size =
                                sizeof(struct ib_flow_spec_action_count);
                flow_resources_add(uflow_res,
@@ -2922,14 +2930,14 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
                return PTR_ERR(obj);
 
        pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
-       if (!pd) {
-               err = -EINVAL;
+       if (IS_ERR(pd)) {
+               err = PTR_ERR(pd);
                goto err_uobj;
        }
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
-       if (!cq) {
-               err = -EINVAL;
+       if (IS_ERR(cq)) {
+               err = PTR_ERR(cq);
                goto err_put_pd;
        }
 
@@ -3030,8 +3038,8 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs)
                return -EINVAL;
 
        wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, cmd.wq_handle, attrs);
-       if (!wq)
-               return -EINVAL;
+       if (IS_ERR(wq))
+               return PTR_ERR(wq);
 
        if (cmd.attr_mask & IB_WQ_FLAGS) {
                wq_attr.flags = cmd.flags;
@@ -3114,8 +3122,8 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
                        num_read_wqs++) {
                wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ,
                                       wqs_handles[num_read_wqs], attrs);
-               if (!wq) {
-                       err = -EINVAL;
+               if (IS_ERR(wq)) {
+                       err = PTR_ERR(wq);
                        goto put_wqs;
                }
 
@@ -3270,8 +3278,8 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs)
        }
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp) {
-               err = -EINVAL;
+       if (IS_ERR(qp)) {
+               err = PTR_ERR(qp);
                goto err_uobj;
        }
 
@@ -3417,15 +3425,15 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
        if (ib_srq_has_cq(cmd->srq_type)) {
                attr.ext.cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
                                                cmd->cq_handle, attrs);
-               if (!attr.ext.cq) {
-                       ret = -EINVAL;
+               if (IS_ERR(attr.ext.cq)) {
+                       ret = PTR_ERR(attr.ext.cq);
                        goto err_put_xrcd;
                }
        }
 
        pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, attrs);
-       if (!pd) {
-               ret = -EINVAL;
+       if (IS_ERR(pd)) {
+               ret = PTR_ERR(pd);
                goto err_put_cq;
        }
 
@@ -3532,8 +3540,8 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs)
                return ret;
 
        srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
-       if (!srq)
-               return -EINVAL;
+       if (IS_ERR(srq))
+               return PTR_ERR(srq);
 
        attr.max_wr    = cmd.max_wr;
        attr.srq_limit = cmd.srq_limit;
@@ -3560,8 +3568,8 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs)
                return ret;
 
        srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
-       if (!srq)
-               return -EINVAL;
+       if (IS_ERR(srq))
+               return PTR_ERR(srq);
 
        ret = ib_query_srq(srq, &attr);
 
@@ -3686,8 +3694,8 @@ static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs)
                return -EOPNOTSUPP;
 
        cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
-       if (!cq)
-               return -EINVAL;
+       if (IS_ERR(cq))
+               return PTR_ERR(cq);
 
        ret = rdma_set_cq_moderation(cq, cmd.attr.cq_count, cmd.attr.cq_period);
 
index fe05121169589f3cdf6622dfe24e461119f73614..555ea3d142a46bfb1c03d7aeecbd88b4938a0b00 100644 (file)
@@ -34,7 +34,7 @@
 static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
 {
        if (IS_ERR(uobj))
-               return NULL;
+               return ERR_CAST(uobj);
        return uobj->object;
 }
 #define uobj_get_obj_read(_object, _type, _id, _attrs)                         \