* [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata
@ 2026-06-27 2:56 Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 1/5] RDMA/irdma: Enforce empty udata input for no-input ops Jacob Moroni
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
This series brings irdma up to uverbs_robust_udata compliance.
The driver has been audited to confirm that:
1. Methods which do not accept udata input perform an explicit
check for no (or zero value) input.
2. Methods which do accept input perform the correct validation
to ensure that additional udata beyond the kernel's current
ABI definition is zero, and to enforce the required minimum
length.
3. Methods which do not return udata responses use the proper
helper.
The irdma driver is backwards compatible with the legacy i40iw
provider, so special care was taken to avoid breaking any legacy
binaries, as there were some small differences in the ABI/semantics.
This has passed the rdma-unit-test suite using the normal irdma
provider from upstream rdma-core.
Jacob Moroni (5):
RDMA/irdma: Enforce empty udata input for no-input ops
RDMA/irdma: Use robust udata input copy helpers
RDMA/irdma: Use ib_respond_empty_udata where applicable
RDMA/irdma: Use robust udata helper for QP creation
RDMA/irdma: Enable uverbs_robust_udata compliance flag
drivers/infiniband/hw/irdma/verbs.c | 135 ++++++++++++++++++----------
include/uapi/rdma/irdma-abi.h | 1 +
2 files changed, 87 insertions(+), 49 deletions(-)
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH rdma-next 1/5] RDMA/irdma: Enforce empty udata input for no-input ops
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
@ 2026-06-27 2:56 ` Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 2/5] RDMA/irdma: Use robust udata input copy helpers Jacob Moroni
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Validate that the udata input buffer is empty for operations
that do not expect input data from userspace.
The irdma rdma-core provider as well as the legacy i40iw
provider were both checked to ensure they never passed any
udata to these ops.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 48 +++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index b79f5afe68e5..e1c894fba2af 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -410,6 +410,10 @@ static int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata)
if (udata && udata->outlen < IRDMA_ALLOC_PD_MIN_RESP_LEN)
return -EINVAL;
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
+
err = irdma_alloc_rsrc(rf, rf->allocated_pds, rf->max_pd, &pd_id,
&rf->next_pd);
if (err)
@@ -445,6 +449,11 @@ static int irdma_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
{
struct irdma_pd *iwpd = to_iwpd(ibpd);
struct irdma_device *iwdev = to_iwdev(ibpd->device);
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
irdma_free_rsrc(iwdev->rf, iwdev->rf->allocated_pds, iwpd->sc_pd.pd_id);
@@ -542,6 +551,11 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
{
struct irdma_qp *iwqp = to_iwqp(ibqp);
struct irdma_device *iwdev = iwqp->iwdev;
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
iwqp->sc_qp.qp_uk.destroy_pending = true;
@@ -1959,6 +1973,11 @@ static int irdma_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
struct irdma_device *iwdev = to_iwdev(ibsrq->device);
struct irdma_srq *iwsrq = to_iwsrq(ibsrq);
struct irdma_sc_srq *srq = &iwsrq->sc_srq;
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
irdma_srq_wq_destroy(iwdev->rf, srq);
irdma_srq_free_rsrc(iwdev->rf, iwsrq);
@@ -1979,6 +1998,11 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
struct irdma_sc_ceq *ceq = dev->ceq[cq->ceq_id];
struct irdma_ceq *iwceq = container_of(ceq, struct irdma_ceq, sc_ceq);
unsigned long flags;
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
spin_lock_irqsave(&iwcq->lock, flags);
if (!list_empty(&iwcq->cmpl_generated))
@@ -2195,6 +2219,10 @@ static int irdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
struct cqp_cmds_info *cqp_info;
int status;
+ status = ib_is_udata_in_empty(udata);
+ if (status)
+ return status;
+
if (attr_mask & IB_SRQ_MAX_WR)
return -EINVAL;
@@ -3035,6 +3063,10 @@ static int irdma_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
int err_code;
u32 stag;
+ err_code = ib_is_udata_in_empty(udata);
+ if (err_code)
+ return err_code;
+
stag = irdma_create_stag(iwdev);
if (!stag)
return -ENOMEM;
@@ -3785,6 +3817,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
struct ib_umem_dmabuf *umem_dmabuf;
int ret;
+ ret = ib_is_udata_in_empty(udata);
+ if (ret)
+ return ERR_PTR(ret);
+
if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
return ERR_PTR(-EINVAL);
@@ -3973,6 +4009,10 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
bool dmabuf_revocable = iwmr->region && iwmr->region->is_dmabuf;
int ret;
+ ret = ib_is_udata_in_empty(udata);
+ if (ret)
+ return ret;
+
if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) {
if (iwmr->region) {
struct irdma_ucontext *ucontext;
@@ -5292,6 +5332,10 @@ static int irdma_create_user_ah(struct ib_ah *ibah,
if (udata->outlen < IRDMA_CREATE_AH_MIN_RESP_LEN)
return -EINVAL;
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
+
err = irdma_setup_ah(ibah, attr);
if (err)
return err;
@@ -5340,6 +5384,10 @@ static int irdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *attr,
struct irdma_device *iwdev = to_iwdev(ibah->pd->device);
int err;
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
+
err = irdma_setup_ah(ibah, attr);
if (err)
return err;
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH rdma-next 2/5] RDMA/irdma: Use robust udata input copy helpers
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 1/5] RDMA/irdma: Enforce empty udata input for no-input ops Jacob Moroni
@ 2026-06-27 2:56 ` Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 3/5] RDMA/irdma: Use ib_respond_empty_udata where applicable Jacob Moroni
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Replace the use of ib_copy_from_udata() with
ib_copy_validate_udata_in() where applicable.
For each modified call site, the last argument of
ib_copy_validate_udata_in() was determined by taking
the last member of the ABI struct as per its original
definition (i.e., when it was first committed).
Some methods like irdma_create_cq required special care
because the last member of the current ABI def is beyond
that of the legacy i40iw's ABI def which we need to
remain compatible with. In some other cases like modify_qp,
the legacy i40iw provider never provided any udata at all
so the validation is only performed if inlen > 0.
irdma_create_qp is more challenging because the legacy ABI
was actually larger but the additional fields were never used,
and even worse, never initialized in the provider. This will
be handled in a followup commit.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 61 +++++++++++++----------------
1 file changed, 27 insertions(+), 34 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index e1c894fba2af..19dcc475c355 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1554,10 +1554,13 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
iwqp->ibqp_state = attr->qp_state;
spin_unlock_irqrestore(&iwqp->lock, flags);
+ /* legacy i40iw does not send any udata. For
+ * current irdma, validate against ABI def.
+ */
if (udata && udata->inlen) {
- if (ib_copy_from_udata(&ureq, udata,
- min(sizeof(ureq), udata->inlen)))
- return -EINVAL;
+ ret = ib_copy_validate_udata_in(udata, ureq, rsvd);
+ if (ret)
+ return ret;
irdma_flush_wqes(iwqp,
(ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) |
@@ -1758,9 +1761,9 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
iwqp->ibqp_state = attr->qp_state;
spin_unlock_irqrestore(&iwqp->lock, flags);
if (udata && udata->inlen) {
- if (ib_copy_from_udata(&ureq, udata,
- min(sizeof(ureq), udata->inlen)))
- return -EINVAL;
+ err = ib_copy_validate_udata_in(udata, ureq, rsvd);
+ if (err)
+ return err;
irdma_flush_wqes(iwqp,
(ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) |
@@ -2033,7 +2036,6 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
struct ib_udata *udata)
{
-#define IRDMA_RESIZE_CQ_MIN_REQ_LEN offsetofend(struct irdma_resize_cq_req, user_cq_buffer)
struct irdma_cq *iwcq = to_iwcq(ibcq);
struct irdma_sc_dev *dev = iwcq->sc_cq.dev;
struct irdma_cqp_request *cqp_request;
@@ -2057,9 +2059,6 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
IRDMA_FEATURE_CQ_RESIZE))
return -EOPNOTSUPP;
- if (udata && udata->inlen < IRDMA_RESIZE_CQ_MIN_REQ_LEN)
- return -EINVAL;
-
if (entries > rf->max_cqe)
return -EINVAL;
@@ -2089,9 +2088,9 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
rdma_udata_to_drv_context(udata, struct irdma_ucontext,
ibucontext);
- if (ib_copy_from_udata(&req, udata,
- min(sizeof(req), udata->inlen)))
- return -EINVAL;
+ ret = ib_copy_validate_udata_in(udata, req, user_cq_buffer);
+ if (ret)
+ return ret;
spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
iwpbl_buf = irdma_get_pbl((unsigned long)req.user_cq_buffer,
@@ -2265,24 +2264,20 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev,
struct irdma_srq_init_info *info,
struct ib_udata *udata)
{
-#define IRDMA_CREATE_SRQ_MIN_REQ_LEN \
- offsetofend(struct irdma_create_srq_req, user_shadow_area)
struct irdma_create_srq_req req = {};
struct irdma_ucontext *ucontext;
struct irdma_srq_mr *srqmr;
struct irdma_pbl *iwpbl;
unsigned long flags;
+ int ret;
iwsrq->user_mode = true;
ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext,
ibucontext);
- if (udata->inlen < IRDMA_CREATE_SRQ_MIN_REQ_LEN)
- return -EINVAL;
-
- if (ib_copy_from_udata(&req, udata,
- min(sizeof(req), udata->inlen)))
- return -EFAULT;
+ ret = ib_copy_validate_udata_in(udata, req, user_shadow_area);
+ if (ret)
+ return ret;
spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags);
iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf,
@@ -2487,7 +2482,6 @@ static int irdma_create_cq(struct ib_cq *ibcq,
const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs)
{
-#define IRDMA_CREATE_CQ_MIN_REQ_LEN offsetofend(struct irdma_create_cq_req, user_cq_buf)
#define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size)
struct ib_udata *udata = &attrs->driver_udata;
struct ib_device *ibdev = ibcq->device;
@@ -2511,8 +2505,7 @@ static int irdma_create_cq(struct ib_cq *ibcq,
if (err_code)
return err_code;
- if (udata && (udata->inlen < IRDMA_CREATE_CQ_MIN_REQ_LEN ||
- udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN))
+ if (udata && udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)
return -EINVAL;
err_code = irdma_alloc_rsrc(rf, rf->allocated_cqs, rf->max_cq, &cq_num,
@@ -2554,11 +2547,14 @@ static int irdma_create_cq(struct ib_cq *ibcq,
ucontext =
rdma_udata_to_drv_context(udata, struct irdma_ucontext,
ibucontext);
- if (ib_copy_from_udata(&req, udata,
- min(sizeof(req), udata->inlen))) {
- err_code = -EFAULT;
+ /* Even though the last member of struct irdma_create_cq_req
+ * was always user_shadow_area, we need backwards compat with
+ * the legacy i40iw struct i40iw_ucreate_cq which stopped
+ * at user_cq_buffer.
+ */
+ err_code = ib_copy_validate_udata_in(udata, req, user_cq_buf);
+ if (err_code)
goto cq_free_rsrc;
- }
spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
@@ -3541,7 +3537,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
struct ib_dmah *dmah,
struct ib_udata *udata)
{
-#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages)
struct irdma_device *iwdev = to_iwdev(pd->device);
struct irdma_mem_reg_req req = {};
struct ib_umem *region = NULL;
@@ -3554,9 +3549,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
return ERR_PTR(-EINVAL);
- if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN)
- return ERR_PTR(-EINVAL);
-
region = ib_umem_get_va(pd->device, start, len, access);
if (IS_ERR(region)) {
@@ -3565,9 +3557,10 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
return (struct ib_mr *)region;
}
- if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) {
+ err = ib_copy_validate_udata_in(udata, req, sq_pages);
+ if (err) {
ib_umem_release(region);
- return ERR_PTR(-EFAULT);
+ return ERR_PTR(err);
}
iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type);
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH rdma-next 3/5] RDMA/irdma: Use ib_respond_empty_udata where applicable
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 1/5] RDMA/irdma: Enforce empty udata input for no-input ops Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 2/5] RDMA/irdma: Use robust udata input copy helpers Jacob Moroni
@ 2026-06-27 2:56 ` Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 4/5] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 5/5] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
4 siblings, 0 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Methods that do not provide any user response should use
the ib_respond_empty_udata() helper to ensure that user
response buffers are cleared.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 19dcc475c355..d06df520d9be 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -457,7 +457,7 @@ static int irdma_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
irdma_free_rsrc(iwdev->rf, iwdev->rf->allocated_pds, iwpd->sc_pd.pd_id);
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
@@ -585,7 +585,7 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
iwdev->rf->hwqp1_rsvd = false;
irdma_free_qp_rsrc(iwqp);
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
@@ -1984,7 +1984,7 @@ static int irdma_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
irdma_srq_wq_destroy(iwdev->rf, srq);
irdma_srq_free_rsrc(iwdev->rf, iwsrq);
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
@@ -2024,7 +2024,7 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
spin_unlock_irqrestore(&iwceq->ce_lock, flags);
irdma_cq_free_rsrc(iwdev->rf, iwcq);
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
@@ -2256,7 +2256,7 @@ static int irdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
iwsrq->sc_srq.srq_limit = info->srq_limit;
- return 0;
+ return ib_respond_empty_udata(udata);
}
static int irdma_setup_umode_srq(struct irdma_device *iwdev,
@@ -3076,7 +3076,7 @@ static int irdma_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
return err_code;
}
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
@@ -4043,7 +4043,7 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
kfree(iwmr);
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH rdma-next 4/5] RDMA/irdma: Use robust udata helper for QP creation
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
` (2 preceding siblings ...)
2026-06-27 2:56 ` [PATCH rdma-next 3/5] RDMA/irdma: Use ib_respond_empty_udata where applicable Jacob Moroni
@ 2026-06-27 2:56 ` Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 5/5] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
4 siblings, 0 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
Replace the manual udata input copy and validation during
QP creation with the robust helper.
The irdma driver is backwards compatible with the legacy
i40iw userspace provider. The current create_qp ABI contains
two 8 byte fields. The legacy i40iw ABI was the same but
also contained two additional fields which were never actually
used. Furthermore, the i40iw userspace provider never explicitly
zero-initialized those extra fields, so there is a chance that
existing binaries are passing non-zero garbage values down
to the kernel.
Previously, the irdma driver only copied out the first 16
bytes and did not have any check for the rest of the buffer
being zero, so that additional garbage didn't matter.
By switching to ib_copy_validate_udata_in(), we will now be
checking to ensure that data beyond the kernel's definition
of the request is all zero.
In order to avoid breaking legacy binaries, we therefore need
to increase the request structure size to cover those garbage
fields.
- Legacy binaries will continue to pass down a 32 byte request,
with the driver copying the entire 32 bytes out but ignoring
the second 16 bytes, just as before.
- Newer binaries will pass down the normal 16 byte request. The
ib_copy_validate_udata_in() call will allow this to succeed
because we use user_compl_ctx as our minimum length (16 bytes).
- If the request is ever extended, the new fields would be
added after the "don't use" fields and would work as per
the normal uAPI mechanism.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 11 +++--------
include/uapi/rdma/irdma-abi.h | 1 +
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index d06df520d9be..f07c11a0569b 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -638,12 +638,9 @@ static int irdma_setup_umode_qp(struct ib_udata *udata,
unsigned long flags;
int ret;
- ret = ib_copy_from_udata(&req, udata,
- min(sizeof(req), udata->inlen));
- if (ret) {
- ibdev_dbg(&iwdev->ibdev, "VERBS: ib_copy_from_data fail\n");
+ ret = ib_copy_validate_udata_in(udata, req, user_compl_ctx);
+ if (ret)
return ret;
- }
iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx;
iwqp->user_mode = 1;
@@ -962,7 +959,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata)
{
-#define IRDMA_CREATE_QP_MIN_REQ_LEN offsetofend(struct irdma_create_qp_req, user_compl_ctx)
#define IRDMA_CREATE_QP_MIN_RESP_LEN offsetofend(struct irdma_create_qp_resp, rsvd)
struct ib_pd *ibpd = ibqp->pd;
struct irdma_pd *iwpd = to_iwpd(ibpd);
@@ -994,8 +990,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
if (err_code)
return err_code;
- if (udata && (udata->inlen < IRDMA_CREATE_QP_MIN_REQ_LEN ||
- udata->outlen < IRDMA_CREATE_QP_MIN_RESP_LEN))
+ if (udata && udata->outlen < IRDMA_CREATE_QP_MIN_RESP_LEN)
return -EINVAL;
init_info.vsi = &iwdev->vsi;
diff --git a/include/uapi/rdma/irdma-abi.h b/include/uapi/rdma/irdma-abi.h
index 36f20802bcc8..38155affc8b4 100644
--- a/include/uapi/rdma/irdma-abi.h
+++ b/include/uapi/rdma/irdma-abi.h
@@ -88,6 +88,7 @@ struct irdma_create_srq_resp {
struct irdma_create_qp_req {
__aligned_u64 user_wqe_bufs;
__aligned_u64 user_compl_ctx;
+ __aligned_u64 legacy_dontuse[2];
};
struct irdma_mem_reg_req {
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH rdma-next 5/5] RDMA/irdma: Enable uverbs_robust_udata compliance flag
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
` (3 preceding siblings ...)
2026-06-27 2:56 ` [PATCH rdma-next 4/5] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
@ 2026-06-27 2:56 ` Jacob Moroni
4 siblings, 0 replies; 6+ messages in thread
From: Jacob Moroni @ 2026-06-27 2:56 UTC (permalink / raw)
To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni
The irdma driver has been audited to confirm that:
1. Methods which do not accept udata input perform an explicit
check for no (or zero value) input.
2. Methods which do accept input perform the correct validation
to ensure that additional udata beyond the kernel's current
ABI definition is zero, and to enforce the required minimum
length.
3. Methods which do not return udata responses use the proper
helper.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
drivers/infiniband/hw/irdma/verbs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index f07c11a0569b..6d97c32d7015 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -5458,6 +5458,7 @@ static const struct ib_device_ops irdma_dev_ops = {
.owner = THIS_MODULE,
.driver_id = RDMA_DRIVER_IRDMA,
.uverbs_abi_ver = IRDMA_ABI_VER,
+ .uverbs_robust_udata = 1,
.alloc_hw_port_stats = irdma_alloc_hw_port_stats,
.alloc_mr = irdma_alloc_mr,
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-27 2:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-27 2:56 [PATCH rdma-next 0/5] RDMA/irdma: Adopt robust udata Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 1/5] RDMA/irdma: Enforce empty udata input for no-input ops Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 2/5] RDMA/irdma: Use robust udata input copy helpers Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 3/5] RDMA/irdma: Use ib_respond_empty_udata where applicable Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 4/5] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
2026-06-27 2:56 ` [PATCH rdma-next 5/5] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox