]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
RDMA: Update the query_device() op
authorJason Gunthorpe <jgg@nvidia.com>
Tue, 26 May 2026 16:15:06 +0000 (13:15 -0300)
committerJason Gunthorpe <jgg@nvidia.com>
Wed, 3 Jun 2026 18:12:43 +0000 (15:12 -0300)
This op hasn't followed the normal pattern of passing NULL for udata when
invoked by the kernel. Instead the kernel caller creates a dummy ib_udata
on the stack and passes that in. It does not seem to currently be a bug,
but this flow should be modernized to use the new API flow and in the
process accept NULL as well.

Only mlx4 uses an input request structure, have every other driver call
ib_is_udata_in_empty() to enforce the lack of request structs.

Use ib_respond_empty_udata() in every driver that does not use a response
struct.

Ensure a check for NULL udata before calling ib_respond_udata() in
bnxt_re, efa, and mlx5.

Make mlx4 safe to be called with NULL.

Link: https://patch.msgid.link/r/2-v1-922fa8e828ba+f7-ib_udata_stack_jgg@nvidia.com
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
17 files changed:
drivers/infiniband/core/device.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/cxgb4/provider.c
drivers/infiniband/hw/erdma/erdma_verbs.c
drivers/infiniband/hw/hns/hns_roce_main.c
drivers/infiniband/hw/ionic/ionic_ibdev.c
drivers/infiniband/hw/irdma/verbs.c
drivers/infiniband/hw/mana/main.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/usnic/usnic_ib_verbs.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
drivers/infiniband/sw/rdmavt/vt.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/siw/siw_verbs.c

index 21ada0fe905994421dfa79e8a60bb71b2fc50a2a..b8193e077a746f50f77bcdf756cc889e9814f659 100644 (file)
@@ -1246,7 +1246,6 @@ out:
  */
 static int setup_device(struct ib_device *device)
 {
-       struct ib_udata uhw = {.outlen = 0, .inlen = 0};
        int ret;
 
        ib_device_check_mandatory(device);
@@ -1258,7 +1257,7 @@ static int setup_device(struct ib_device *device)
        }
 
        memset(&device->attrs, 0, sizeof(device->attrs));
-       ret = device->ops.query_device(device, &device->attrs, &uhw);
+       ret = device->ops.query_device(device, &device->attrs, NULL);
        if (ret) {
                dev_warn(&device->dev,
                         "Couldn't query the device attributes\n");
index c1c4ddc615e28655b4665d7009274f8848fa090e..0ca549c2f5cb0fefb3ea4f6d87a2d726804bb94c 100644 (file)
@@ -265,7 +265,10 @@ int bnxt_re_query_device(struct ib_device *ibdev,
                resp.packet_pacing_caps.supported_qpts =
                        1 << IB_QPT_RC;
        }
-       return ib_respond_udata(udata, resp);
+
+       if (udata)
+               return ib_respond_udata(udata, resp);
+       return 0;
 }
 
 int bnxt_re_modify_device(struct ib_device *ibdev,
index 0e3827022c63da4b9bf7b1ad62301f01df8a56b8..e1eec37ee8222a895373c94ef7f9ab9b51b3b41e 100644 (file)
@@ -259,11 +259,13 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
 {
 
        struct c4iw_dev *dev;
+       int err;
 
        pr_debug("ibdev %p\n", ibdev);
 
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        dev = to_c4iw_dev(ibdev);
        addrconf_addr_eui48((u8 *)&props->sys_image_guid,
@@ -298,7 +300,7 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
        props->max_fast_reg_page_list_len =
                t4_max_fr_depth(dev->rdev.lldi.ulptx_memwrite_dsgl && use_dsgl);
 
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 static int c4iw_query_port(struct ib_device *ibdev, u32 port,
index 9a9dc78c7ab64690a8b9ddc7c90208d1143c97c2..74afe6eb18b0bcee6af5d7ee2f6bf3e040a77844 100644 (file)
@@ -315,9 +315,14 @@ erdma_user_mmap_entry_insert(struct erdma_ucontext *uctx, void *address,
 }
 
 int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
-                      struct ib_udata *unused)
+                      struct ib_udata *udata)
 {
        struct erdma_dev *dev = to_edev(ibdev);
+       int err;
+
+       err = ib_is_udata_in_empty(udata);
+       if (err)
+               return err;
 
        memset(attr, 0, sizeof(*attr));
 
@@ -358,7 +363,7 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
                addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
                                    dev->netdev->dev_addr);
 
-       return 0;
+       return ib_respond_empty_udata(udata);
 }
 
 int erdma_query_gid(struct ib_device *ibdev, u32 port, int idx,
index 77bad9f5d482bbf5b43cf5202ebd0cb8bdc277e3..c6f633bd5a3402d1271dc47bb91f932a99d44874 100644 (file)
@@ -221,6 +221,11 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
                                 struct ib_udata *uhw)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
+       int ret;
+
+       ret = ib_is_udata_in_empty(uhw);
+       if (ret)
+               return ret;
 
        memset(props, 0, sizeof(*props));
 
@@ -274,7 +279,7 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
        if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_XRC)
                props->device_cap_flags |= IB_DEVICE_XRC;
 
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 static int hns_roce_query_port(struct ib_device *ib_dev, u32 port_num,
index 73a616ae35023630a9b38f17af410c3c283655c5..b0449c75f8938f131256f226efaa4762261a4684 100644 (file)
@@ -25,6 +25,11 @@ static int ionic_query_device(struct ib_device *ibdev,
 {
        struct ionic_ibdev *dev = to_ionic_ibdev(ibdev);
        struct net_device *ndev;
+       int err;
+
+       err = ib_is_udata_in_empty(udata);
+       if (err)
+               return err;
 
        ndev = ib_device_get_netdev(ibdev, 1);
        addrconf_ifid_eui48((u8 *)&attr->sys_image_guid, ndev);
@@ -69,7 +74,7 @@ static int ionic_query_device(struct ib_device *ibdev,
        attr->max_fast_reg_page_list_len = dev->lif_cfg.npts_per_lif / 2;
        attr->max_pkeys = IONIC_PKEY_TBL_LEN;
 
-       return 0;
+       return ib_respond_empty_udata(udata);
 }
 
 static int ionic_query_port(struct ib_device *ibdev, u32 port,
index baee48df5fdf36ed2209634512a1d01f02a44f7a..b19edf31c8000a5c67859bce5d3bf245adca3a1e 100644 (file)
@@ -16,9 +16,11 @@ static int irdma_query_device(struct ib_device *ibdev,
        struct irdma_pci_f *rf = iwdev->rf;
        struct pci_dev *pcidev = iwdev->rf->pcidev;
        struct irdma_hw_attrs *hw_attrs = &rf->sc_dev.hw_attrs;
+       int err;
 
-       if (udata->inlen || udata->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(udata);
+       if (err)
+               return err;
 
        memset(props, 0, sizeof(*props));
        addrconf_addr_eui48((u8 *)&props->sys_image_guid,
@@ -74,7 +76,7 @@ static int irdma_query_device(struct ib_device *ibdev,
        if (hw_attrs->uk_attrs.hw_rev >= IRDMA_GEN_3)
                props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B;
 
-       return 0;
+       return ib_respond_empty_udata(udata);
 }
 
 /**
index 1e93df6455f5b74f82c28255fd0001b3330ed784..a86f80b911efc9ba6c0249f7e6bb744565cdd52b 100644 (file)
@@ -549,6 +549,11 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
 {
        struct mana_ib_dev *dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
        struct pci_dev *pdev = to_pci_dev(mdev_to_gc(dev)->dev);
+       int err;
+
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        memset(props, 0, sizeof(*props));
        props->vendor_id = pdev->vendor;
@@ -576,7 +581,7 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
        if (!mana_ib_is_rnic(dev))
                props->raw_packet_caps = IB_RAW_PACKET_CAP_IP_CSUM;
 
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 int mana_ib_query_port(struct ib_device *ibdev, u32 port,
index d50743f090bf216cea15eeac9845f0ce17bc587f..17073e8f105aabf05a6e660c2161cf672f503049 100644 (file)
@@ -444,8 +444,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        struct mlx4_uverbs_ex_query_device cmd;
        struct mlx4_uverbs_ex_query_device_resp resp = {};
        struct mlx4_clock_params clock_params;
+       size_t uhw_outlen = uhw ? uhw->outlen : 0;
 
-       if (uhw->inlen) {
+       if (uhw && uhw->inlen) {
                err = ib_copy_validate_udata_in_cm(uhw, cmd, reserved, 0);
                if (err)
                        return err;
@@ -572,7 +573,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->cq_caps.max_cq_moderation_count = MLX4_MAX_CQ_COUNT;
        props->cq_caps.max_cq_moderation_period = MLX4_MAX_CQ_PERIOD;
 
-       if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
+       if (uhw_outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
                resp.response_length += sizeof(resp.hca_core_clock_offset);
                if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) {
                        resp.comp_mask |= MLX4_IB_QUERY_DEV_RESP_MASK_CORE_CLOCK_OFFSET;
@@ -580,14 +581,14 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                }
        }
 
-       if (uhw->outlen >= resp.response_length +
+       if (uhw_outlen >= resp.response_length +
            sizeof(resp.max_inl_recv_sz)) {
                resp.response_length += sizeof(resp.max_inl_recv_sz);
                resp.max_inl_recv_sz  = dev->dev->caps.max_rq_sg *
                        sizeof(struct mlx4_wqe_data_seg);
        }
 
-       if (offsetofend(typeof(resp), rss_caps) <= uhw->outlen) {
+       if (offsetofend(typeof(resp), rss_caps) <= uhw_outlen) {
                if (props->rss_caps.supported_qpts) {
                        resp.rss_caps.rx_hash_function =
                                MLX4_IB_RX_HASH_FUNC_TOEPLITZ;
@@ -611,7 +612,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                                       sizeof(resp.rss_caps);
        }
 
-       if (offsetofend(typeof(resp), tso_caps) <= uhw->outlen) {
+       if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen) {
                if (dev->dev->caps.max_gso_sz &&
                    ((mlx4_ib_port_link_layer(ibdev, 1) ==
                    IB_LINK_LAYER_ETHERNET) ||
@@ -625,7 +626,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                                       sizeof(resp.tso_caps);
        }
 
-       if (uhw->outlen) {
+       if (uhw_outlen) {
                err = ib_respond_udata(uhw, resp);
                if (err)
                        goto out;
index 23e387dba79da8b40bf5a054985595e538e87941..f90f67afc8fabe02cd08f9fe49f53e2ec457d1ec 100644 (file)
@@ -55,16 +55,19 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
 {
        struct ib_smp *in_mad;
        struct ib_smp *out_mad;
-       int err = -ENOMEM;
+       int err;
        struct mthca_dev *mdev = to_mdev(ibdev);
 
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        in_mad = kzalloc_obj(*in_mad);
        out_mad = kmalloc_obj(*out_mad);
-       if (!in_mad || !out_mad)
+       if (!in_mad || !out_mad) {
+               err = -ENOMEM;
                goto out;
+       }
 
        memset(props, 0, sizeof *props);
 
@@ -111,7 +114,7 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
        props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
                                           props->max_mcast_grp;
 
-       err = 0;
+       err = ib_respond_empty_udata(uhw);
  out:
        kfree(in_mad);
        kfree(out_mad);
index 69caadcff810ed4c8568f463d4d7a23f596b895a..53ba32d168a17cdbff667e306a264cd106b2ad52 100644 (file)
@@ -68,9 +68,11 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
                        struct ib_udata *uhw)
 {
        struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+       int err;
 
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        memset(attr, 0, sizeof *attr);
        memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
@@ -110,7 +112,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
        attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
        attr->max_fast_reg_page_list_len = dev->attr.max_pages_per_frmr;
        attr->max_pkeys = 1;
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
index 7195eeede5301374addafb9f54064d49b8ff33c2..c90a1b5c8ee7d1821cdd07f51b3274b025877153 100644 (file)
@@ -105,6 +105,7 @@ int qedr_query_device(struct ib_device *ibdev,
 {
        struct qedr_dev *dev = get_qedr_dev(ibdev);
        struct qedr_device_attr *qattr = &dev->attr;
+       int rc;
 
        if (!dev->rdma_ctx) {
                DP_ERR(dev,
@@ -113,6 +114,10 @@ int qedr_query_device(struct ib_device *ibdev,
                return -EINVAL;
        }
 
+       rc = ib_is_udata_in_empty(udata);
+       if (rc)
+               return rc;
+
        memset(attr, 0, sizeof(*attr));
 
        attr->fw_ver = qattr->fw_ver;
@@ -155,7 +160,7 @@ int qedr_query_device(struct ib_device *ibdev,
        attr->max_pkeys = qattr->max_pkey;
        attr->max_ah = qattr->max_ah;
 
-       return 0;
+       return ib_respond_empty_udata(udata);
 }
 
 static inline void get_link_speed_and_width(int speed, u16 *ib_speed,
index 261f18a83685437657442fe151b190892e3337b4..dc355b00f61cecebdcc309eca43a45b528ee6a34 100644 (file)
@@ -275,10 +275,12 @@ int usnic_ib_query_device(struct ib_device *ibdev,
        union ib_gid gid;
        struct ethtool_drvinfo info;
        int qp_per_vf;
+       int err;
 
        usnic_dbg("\n");
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        mutex_lock(&us_ibdev->usdev_lock);
        us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
@@ -322,7 +324,7 @@ int usnic_ib_query_device(struct ib_device *ibdev,
         * max_qp_wr, max_sge, max_sge_rd, max_cqe */
        mutex_unlock(&us_ibdev->usdev_lock);
 
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 int usnic_ib_query_port(struct ib_device *ibdev, u32 port,
index b9c3202b9545e386461cdb45ec94ce29cc03aefc..1d29a535f76a8c24c840a32875e1cf501ab1fc79 100644 (file)
@@ -67,9 +67,11 @@ int pvrdma_query_device(struct ib_device *ibdev,
                        struct ib_udata *uhw)
 {
        struct pvrdma_dev *dev = to_vdev(ibdev);
+       int err;
 
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
 
        props->fw_ver = dev->dsr->caps.fw_ver;
        props->sys_image_guid = dev->dsr->caps.sys_image_guid;
@@ -114,7 +116,7 @@ int pvrdma_query_device(struct ib_device *ibdev,
        props->device_cap_flags |= IB_DEVICE_PORT_ACTIVE_EVENT |
                                   IB_DEVICE_RC_RNR_NAK_GEN;
 
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 /**
index 40aa64208364708822818abd4b27acb6d8c2eaf0..5fa3a1f33326890e783fee864658fc8c66536550 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
+#include <rdma/uverbs_ioctl.h>
 #include "vt.h"
 #include "cq.h"
 #include "trace.h"
@@ -79,14 +80,16 @@ static int rvt_query_device(struct ib_device *ibdev,
                            struct ib_udata *uhw)
 {
        struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
+       int err;
 
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
+       err = ib_is_udata_in_empty(uhw);
+       if (err)
+               return err;
        /*
         * Return rvt_dev_info.dparms.props contents
         */
        *props = rdi->dparms.props;
-       return 0;
+       return ib_respond_empty_udata(uhw);
 }
 
 static int rvt_get_numa_node(struct ib_device *ibdev)
index 8edd4dd1f031f4a247eeb572f7c20eb871eb70e7..5815ce34d9704c57c3fd285575947769b2d3814f 100644 (file)
@@ -22,19 +22,13 @@ static int rxe_query_device(struct ib_device *ibdev,
        struct rxe_dev *rxe = to_rdev(ibdev);
        int err;
 
-       if (udata->inlen || udata->outlen) {
-               rxe_dbg_dev(rxe, "malformed udata\n");
-               err = -EINVAL;
-               goto err_out;
-       }
+       err = ib_is_udata_in_empty(udata);
+       if (err)
+               return err;
 
        memcpy(attr, &rxe->attr, sizeof(*attr));
 
-       return 0;
-
-err_out:
-       rxe_err_dev(rxe, "returned err = %d\n", err);
-       return err;
+       return ib_respond_empty_udata(udata);
 }
 
 static int rxe_query_port(struct ib_device *ibdev,
index b34f3d6547ffc7b5e5ac43fdcb22d909e42ef9b8..b74ac85c1b8b8bcc8b83133f467f3e253f08ec7f 100644 (file)
@@ -130,9 +130,11 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
                     struct ib_udata *udata)
 {
        struct siw_device *sdev = to_siw_dev(base_dev);
+       int rv;
 
-       if (udata->inlen || udata->outlen)
-               return -EINVAL;
+       rv = ib_is_udata_in_empty(udata);
+       if (rv)
+               return rv;
 
        memset(attr, 0, sizeof(*attr));
 
@@ -165,7 +167,7 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
        addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
                            sdev->raw_gid);
 
-       return 0;
+       return ib_respond_empty_udata(udata);
 }
 
 int siw_query_port(struct ib_device *base_dev, u32 port,