* [PATCH 0/2] Remove stack ib_udata's
@ 2026-05-26 16:15 Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp Jason Gunthorpe
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
Sashiko pointed out these are dangerous, and the create_qp() one is in
fact a bug. The query_device is just ugly old code.
Remove the stack ib_udata's from both places.
Jason Gunthorpe (2):
RDMA/core: Don't make a dummy ib_udata on the stack in create_qp
RDMA: Update the query_device() op
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/device.c | 3 +--
drivers/infiniband/core/ib_core_uverbs.c | 12 +++++++++++
drivers/infiniband/core/rdma_core.h | 7 +++++++
drivers/infiniband/core/uverbs_cmd.c | 14 +------------
drivers/infiniband/core/uverbs_std_types_qp.c | 3 +--
drivers/infiniband/core/verbs.c | 20 ++++++++++---------
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++++-
drivers/infiniband/hw/cxgb4/provider.c | 8 +++++---
drivers/infiniband/hw/erdma/erdma_verbs.c | 9 +++++++--
drivers/infiniband/hw/hns/hns_roce_main.c | 7 ++++++-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 7 ++++++-
drivers/infiniband/hw/irdma/verbs.c | 8 +++++---
drivers/infiniband/hw/mana/main.c | 7 ++++++-
drivers/infiniband/hw/mlx4/main.c | 13 ++++++------
drivers/infiniband/hw/mthca/mthca_provider.c | 13 +++++++-----
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 +++++---
drivers/infiniband/hw/qedr/verbs.c | 7 ++++++-
drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 8 +++++---
.../infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 8 +++++---
drivers/infiniband/sw/rdmavt/vt.c | 9 ++++++---
drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++---------
drivers/infiniband/sw/siw/siw_verbs.c | 8 +++++---
23 files changed, 124 insertions(+), 76 deletions(-)
base-commit: fd9482545e37fb6b7e04b588ad2bd80a2779776c
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp
2026-05-26 16:15 [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
@ 2026-05-26 16:15 ` Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 2/2] RDMA: Update the query_device() op Jason Gunthorpe
2026-06-03 18:16 ` [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
2 siblings, 0 replies; 4+ messages in thread
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
Sashiko points out the udata for destruction has to be created using
uverbs_get_cleared_udata(). Move it to ib_core_uverbs.c so that the core
qp code can call it. Rework the call chain to pass the struct
uverbs_attr_bundle right up to the driver op callback.
Fixes a possible wild stack reference in drivers during error unwinding,
mlx5 can call rdma_udata_to_drv_context() from destroy_qp() when
destroying a QP.
Fixes: 00a79d6b996d ("RDMA/core: Configure selinux QP during creation")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/ib_core_uverbs.c | 12 +++++++++++
drivers/infiniband/core/rdma_core.h | 7 +++++++
drivers/infiniband/core/uverbs_cmd.c | 14 +------------
drivers/infiniband/core/uverbs_std_types_qp.c | 3 +--
drivers/infiniband/core/verbs.c | 20 ++++++++++---------
6 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index a2c36666e6fcb9..19104c542b270d 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -321,7 +321,7 @@ void nldev_exit(void);
struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller);
void ib_qp_usecnt_inc(struct ib_qp *qp);
diff --git a/drivers/infiniband/core/ib_core_uverbs.c b/drivers/infiniband/core/ib_core_uverbs.c
index b4fc693a3bd8b7..6c3bc9ca1d58ef 100644
--- a/drivers/infiniband/core/ib_core_uverbs.c
+++ b/drivers/infiniband/core/ib_core_uverbs.c
@@ -532,6 +532,18 @@ int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs)
}
EXPORT_SYMBOL(uverbs_destroy_def_handler);
+/*
+ * When calling a destroy function during an error unwind we need to pass in
+ * the udata that is sanitized of all user arguments. Ie from the driver
+ * perspective it looks like no udata was passed.
+ */
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+ attrs->driver_udata = (struct ib_udata){};
+ return &attrs->driver_udata;
+}
+EXPORT_SYMBOL_NS_GPL(uverbs_get_cleared_udata, "rdma_core");
+
/**
* _uverbs_alloc() - Quickly allocate memory for use with a bundle
* @bundle: The bundle
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index b626d3d24d087d..56121103e9f4f5 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -71,7 +71,14 @@ int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
+#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs);
+#else
+static inline struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+ return NULL;
+}
+#endif
/*
* This is the runtime description of the uverbs API, used by the syscall
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 32914007bae66f..41ad11ae1123b7 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -163,17 +163,6 @@ static int uverbs_request_finish(struct uverbs_req_iter *iter)
return 0;
}
-/*
- * When calling a destroy function during an error unwind we need to pass in
- * the udata that is sanitized of all user arguments. Ie from the driver
- * perspective it looks like no udata was passed.
- */
-struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
-{
- attrs->driver_udata = (struct ib_udata){};
- return &attrs->driver_udata;
-}
-
static struct ib_uverbs_completion_event_file *
_ib_uverbs_lookup_comp_file(s32 fd, struct uverbs_attr_bundle *attrs)
{
@@ -1462,8 +1451,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
attr.source_qpn = cmd->source_qpn;
}
- qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
- KBUILD_MODNAME);
+ qp = ib_create_qp_user(device, pd, &attr, attrs, obj, KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
diff --git a/drivers/infiniband/core/uverbs_std_types_qp.c b/drivers/infiniband/core/uverbs_std_types_qp.c
index be0730e8509ed9..fd617903ffcf49 100644
--- a/drivers/infiniband/core/uverbs_std_types_qp.c
+++ b/drivers/infiniband/core/uverbs_std_types_qp.c
@@ -248,8 +248,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(
set_caps(&attr, &cap, true);
mutex_init(&obj->mcast_lock);
- qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
- KBUILD_MODNAME);
+ qp = ib_create_qp_user(device, pd, &attr, attrs, obj, KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index bac87de9cc6735..1500bc09bdc915 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -53,6 +53,7 @@
#include <rdma/rw.h>
#include <rdma/lag.h>
+#include "rdma_core.h"
#include "core_priv.h"
#include <trace/events/rdma_core.h>
@@ -1265,10 +1266,9 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,
static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller)
{
- struct ib_udata dummy = {};
struct ib_qp *qp;
int ret;
@@ -1301,9 +1301,10 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
qp->recv_cq = attr->recv_cq;
rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
- WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
- rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
- ret = dev->ops.create_qp(qp, attr, udata);
+ WARN_ONCE(!uattrs && !caller, "Missing kernel QP owner");
+ rdma_restrack_set_name(&qp->res, uattrs ? NULL : caller);
+ ret = dev->ops.create_qp(qp, attr,
+ uattrs ? &uattrs->driver_udata : NULL);
if (ret)
goto err_create;
@@ -1322,7 +1323,8 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
return qp;
err_security:
- qp->device->ops.destroy_qp(qp, udata ? &dummy : NULL);
+ qp->device->ops.destroy_qp(
+ qp, uattrs ? uverbs_get_cleared_udata(uattrs) : NULL);
err_create:
rdma_restrack_put(&qp->res);
kfree(qp);
@@ -1338,13 +1340,13 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
* @attr: A list of initial attributes required to create the
* QP. If QP creation succeeds, then the attributes are updated to
* the actual capabilities of the created QP.
- * @udata: User data
+ * @uattrs: User ioctl attributes and udata
* @uobj: uverbs obect
* @caller: caller's build-time module name
*/
struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller)
{
struct ib_qp *qp, *xrc_qp;
@@ -1352,7 +1354,7 @@ struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
if (attr->qp_type == IB_QPT_XRC_TGT)
qp = create_qp(dev, pd, attr, NULL, NULL, caller);
else
- qp = create_qp(dev, pd, attr, udata, uobj, NULL);
+ qp = create_qp(dev, pd, attr, uattrs, uobj, NULL);
if (attr->qp_type != IB_QPT_XRC_TGT || IS_ERR(qp))
return qp;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] RDMA: Update the query_device() op
2026-05-26 16:15 [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp Jason Gunthorpe
@ 2026-05-26 16:15 ` Jason Gunthorpe
2026-06-03 18:16 ` [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
2 siblings, 0 replies; 4+ messages in thread
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
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.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/device.c | 3 +--
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++++-
drivers/infiniband/hw/cxgb4/provider.c | 8 +++++---
drivers/infiniband/hw/erdma/erdma_verbs.c | 9 +++++++--
drivers/infiniband/hw/hns/hns_roce_main.c | 7 ++++++-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 7 ++++++-
drivers/infiniband/hw/irdma/verbs.c | 8 +++++---
drivers/infiniband/hw/mana/main.c | 7 ++++++-
drivers/infiniband/hw/mlx4/main.c | 13 +++++++------
drivers/infiniband/hw/mthca/mthca_provider.c | 13 ++++++++-----
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 +++++---
drivers/infiniband/hw/qedr/verbs.c | 7 ++++++-
drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 8 +++++---
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 8 +++++---
drivers/infiniband/sw/rdmavt/vt.c | 9 ++++++---
drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++----------
drivers/infiniband/sw/siw/siw_verbs.c | 8 +++++---
17 files changed, 91 insertions(+), 51 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b89efaaa81ec58..9f9662e9228186 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1245,7 +1245,6 @@ static int assign_name(struct ib_device *device, const char *name)
*/
static int setup_device(struct ib_device *device)
{
- struct ib_udata uhw = {.outlen = 0, .inlen = 0};
int ret;
ib_device_check_mandatory(device);
@@ -1257,7 +1256,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");
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 94aa06e3b828ca..98d65c1b102200 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -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,
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 0e3827022c63da..e1eec37ee8222a 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -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,
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index b59c2e3a5306d1..d9eb8ae2c56fba 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -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,
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 77bad9f5d482bb..c6f633bd5a3402 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -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,
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index 73a616ae350236..b0449c75f8938f 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -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,
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 3f4811bb5514c6..5ba2e63b51036e 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -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);
}
/**
diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c
index 307ae01bf26f34..4dcd048d44b69a 100644
--- a/drivers/infiniband/hw/mana/main.c
+++ b/drivers/infiniband/hw/mana/main.c
@@ -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,
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index d50743f090bf21..17073e8f105aab 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -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;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index afa97d3801f783..079c51003b24a4 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -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);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 383f1d9c15d151..17def9d9ce99ca 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -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,
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 1af908275ca729..cf01078820d8cb 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -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,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 261f18a8368543..dc355b00f61cec 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -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,
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
index b9c3202b9545e3..1d29a535f76a8c 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
@@ -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);
}
/**
diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
index 40aa6420836470..5fa3a1f3332689 100644
--- a/drivers/infiniband/sw/rdmavt/vt.c
+++ b/drivers/infiniband/sw/rdmavt/vt.c
@@ -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)
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 8edd4dd1f031f4..5815ce34d9704c 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -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,
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index b34f3d6547ffc7..b74ac85c1b8b8b 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -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,
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 0/2] Remove stack ib_udata's
2026-05-26 16:15 [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 2/2] RDMA: Update the query_device() op Jason Gunthorpe
@ 2026-06-03 18:16 ` Jason Gunthorpe
2 siblings, 0 replies; 4+ messages in thread
From: Jason Gunthorpe @ 2026-06-03 18:16 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
On Tue, May 26, 2026 at 01:15:04PM -0300, Jason Gunthorpe wrote:
> Sashiko pointed out these are dangerous, and the create_qp() one is in
> fact a bug. The query_device is just ugly old code.
>
> Remove the stack ib_udata's from both places.
>
> Jason Gunthorpe (2):
> RDMA/core: Don't make a dummy ib_udata on the stack in create_qp
> RDMA: Update the query_device() op
>
> drivers/infiniband/core/core_priv.h | 2 +-
> drivers/infiniband/core/device.c | 3 +--
> drivers/infiniband/core/ib_core_uverbs.c | 12 +++++++++++
> drivers/infiniband/core/rdma_core.h | 7 +++++++
> drivers/infiniband/core/uverbs_cmd.c | 14 +------------
> drivers/infiniband/core/uverbs_std_types_qp.c | 3 +--
> drivers/infiniband/core/verbs.c | 20 ++++++++++---------
> drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++++-
> drivers/infiniband/hw/cxgb4/provider.c | 8 +++++---
> drivers/infiniband/hw/erdma/erdma_verbs.c | 9 +++++++--
> drivers/infiniband/hw/hns/hns_roce_main.c | 7 ++++++-
> drivers/infiniband/hw/ionic/ionic_ibdev.c | 7 ++++++-
> drivers/infiniband/hw/irdma/verbs.c | 8 +++++---
> drivers/infiniband/hw/mana/main.c | 7 ++++++-
> drivers/infiniband/hw/mlx4/main.c | 13 ++++++------
> drivers/infiniband/hw/mthca/mthca_provider.c | 13 +++++++-----
> drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 +++++---
> drivers/infiniband/hw/qedr/verbs.c | 7 ++++++-
> drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 8 +++++---
> .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 8 +++++---
> drivers/infiniband/sw/rdmavt/vt.c | 9 ++++++---
> drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++---------
> drivers/infiniband/sw/siw/siw_verbs.c | 8 +++++---
> 23 files changed, 124 insertions(+), 76 deletions(-)
Applied to for-next
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-03 18:16 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26 16:15 [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp Jason Gunthorpe
2026-05-26 16:15 ` [PATCH 2/2] RDMA: Update the query_device() op Jason Gunthorpe
2026-06-03 18:16 ` [PATCH 0/2] Remove stack ib_udata's Jason Gunthorpe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox